组合数
都是一些定义吧。。。
性质1. 1. 1 . ,从n n n 个东西中选k k k 个选和选n − k n-k n − k 个不选是一样的。
性质2. 2. 2 . ,从n + 1 n+1 n + 1 个东西中选k k k 个,可以在其中n n n 个东西中选k k k 个,剩下一个不选,也可以在其中n n n 个东西中选k − 1 k-1 k − 1 个,剩下一个选。
性质2. 2. 2 . 在预处理组合数时经常用到,如:
1 2 3 4 5 6 for (register int i=0 ;i<MAXN;++i){ C[i][0 ]=1 ,C[i][i]=1 ; for (register int j=1 ;j<i;++j){ C[i][j]=(C[i-1 ][j-1 ]+C[i-1 ][j])%MOD; } }
还有一个神奇的性质,我们把( x + a ) n (x+a)^n ( x + a ) n 拆开,变成( x + a ) ( x + a ) . . . . (x+a)(x+a).... ( x + a ) ( x + a ) . . . . 发现x x x 的系数为k k k 时,相当于在n n n 个x x x 中选k k k 个,剩下n − k n-k n − k 个选a a a 所以系数为C n k C_n^k C n k ,所以,( x + a ) n = ∑ k = 0 n C n k x k a n − k (x+a)^n=\sum^n_{k=0}C^k_nx^ka^{n-k} ( x + a ) n = ∑ k = 0 n C n k x k a n − k
根据这个性质,我们把x = 1 x=1 x = 1 ,a = 1 a=1 a = 1 代入,发现∑ i = 0 n C n i = ( 1 + 1 ) n = 2 n \sum^n_{i=0}C^i_n=(1+1)^n=2^n ∑ i = 0 n C n i = ( 1 + 1 ) n = 2 n 。
把x = 1 x=1 x = 1 ,a = − 1 a=-1 a = − 1 代入,发现∑ i = 0 n ( − 1 ) i C n i = ( 1 + ( − 1 ) ) n = 0 \sum^n_{i=0}(-1)^iC^i_n=(1+(-1))^n=0 ∑ i = 0 n ( − 1 ) i C n i = ( 1 + ( − 1 ) ) n = 0
剩下的性质,自己脑补一些场景,也可以证明出来。
卡特兰数
所有奇卡特兰数,下标都满足n = 2 k − 1 n=2^k-1 n = 2 k − 1 (不知道有啥用,手动狗头)
前6 6 6 点基本上都是老生常谈了,长方形填充还是挺巧妙的。
考虑一个可行的方案,必有如图的一个长方形,它的一个顶点在阶梯上,另一个在阶梯的最下面的角上(标成红色),要不然整个长方形不可能填充完。
发现它上方和右方的小阶梯可以构成子状态,y y yy y y 一下,发现F ( n ) = ∑ i = 0 n − 1 ( F ( i ) + F ( n − i − 1 ) ) F(n)=\sum^{n-1}_{i=0}{(F(i)+F(n-i-1))} F ( n ) = ∑ i = 0 n − 1 ( F ( i ) + F ( n − i − 1 ) )
这不就是卡特兰数吗?
GCD&LCM
大家都知道g c d ( x , y ) gcd(x,y) g c d ( x , y ) =g c d ( y , x m o d y ) gcd(y,x\mod y) g c d ( y , x m o d y ) ,我们可以用如下的算法求g c d gcd g c d 。
1 int gcd (int x,int y) {return x%y==0 ?y:gcd (y,x%y);}
我们发现一个数对一个小于它的数取模后至少缩小一半,所以算法复杂度为l o g ( n ) log(n) l o g ( n ) ,实际可能还更小。
拓展欧几里得算法
求a x + b y = c ax+by=c a x + b y = c 的正整数解。
首先根据裴蜀定理,我们知道:g c d ( a , b ) ∣ c gcd(a,b)|c g c d ( a , b ) ∣ c ,否则方程无解。
设d=\\dfracc}{gcd(a,b)} ,则知道a x + b y = g c d ( a , b ) ax+by=gcd(a,b) a x + b y = g c d ( a , b ) 的解,我们把解出的x , y x,y x , y 都乘个d d d 就能得出原方程的解x ′ , y ′ x',y' x ′ , y ′ 。
考虑把问题简单化,只求a x + b y = g c d ( a , b ) ax+by=gcd(a,b) a x + b y = g c d ( a , b ) 的正整数解。
考虑如下的方程:
a x 1 + b y 1 = g c d ( a , b ) ax_1+by_1=gcd(a,b) a x 1 + b y 1 = g c d ( a , b )
b x 2 + ( a m o d b ) y 2 = g c d ( b , a m o d b ) bx_2+(a\mod b)y_2=gcd(b,a\mod b) b x 2 + ( a m o d b ) y 2 = g c d ( b , a m o d b )
我们知道g c d ( a , b ) = g c d ( b , a m o d b ) gcd(a,b)=gcd(b,a\mod b) g c d ( a , b ) = g c d ( b , a m o d b )
所以a x 1 + b y 1 = b x 2 + ( a m o d b ) y 2 ax_1+by_1=bx_2+(a\mod b)y_2 a x 1 + b y 1 = b x 2 + ( a m o d b ) y 2
又知道a m o d b = a − ⌊ a / b ⌋ × b a\mod b=a-\lfloor a/b \rfloor \times b a m o d b = a − ⌊ a / b ⌋ × b
我们把上面的柿子代入:
发现a x 1 + b y 1 = b x 2 + ( a − ⌊ a / b ⌋ × b ) y 2 ax_1+by_1=bx_2+(a-\lfloor a/b \rfloor \times b)y_2 a x 1 + b y 1 = b x 2 + ( a − ⌊ a / b ⌋ × b ) y 2
化一下:a x 1 + b y 1 = a y 2 + b ( x 2 − ⌊ a / b ⌋ × y 2 ) ax_1+by_1=ay_2+b(x_2-\lfloor a/b \rfloor \times y_2) a x 1 + b y 1 = a y 2 + b ( x 2 − ⌊ a / b ⌋ × y 2 )
对比两边系数,我们开心地发现x 1 = y 2 x_1=y_2 x 1 = y 2 ,y 1 = x 2 − ⌊ a / b ⌋ × y 2 y_1=x_2-\lfloor a/b \rfloor \times y_2 y 1 = x 2 − ⌊ a / b ⌋ × y 2 ,于是我们可以根据x 2 , y 2 x_2,y_2 x 2 , y 2 算出x 1 , y 1 x_1,y_1 x 1 , y 1
具体实现的时候,递归求解即可。
模板:
1 2 3 4 5 6 7 8 9 10 11 int gcd (int a,int b,int &d,int &x,int &y) { if (!b){ d=a,x=1 ,y=0 ; return x; } else { gcd (b,a%b,d,y,x); y-=x*(a/b); } return x; }
BSGS (北上广深算法)
已知a , b , p a,b,p a , b , p ,求a x = b ( m o d p ) a^x=b(\mod p) a x = b ( m o d p ) 的正整数解。
考虑折半法,我们设B = P B=\sqrt{P} B = P ,将x x x 化为B × i − j B \times i-j B × i − j 的形式,其中i < B , j < B i<B,j<B i < B , j < B
将x x x 代入原柿子,发现a x = a B × i − j = a B × i / a j a^x=a^{B \times i-j}=a^{B \times i} / a^j a x = a B × i − j = a B × i / a j
把那个a j a^j a j 搞到右边,发现a B × i = b × a j a^{B \times i}=b \times a^j a B × i = b × a j
其中,左右两边只有i , j i,j i , j 两个变量,取值只有B B B 种可能。
考虑把b × a j b \times a^j b × a j 预处理出来,丢进一个m a p map m a p 或哈希表里面。
后面一个一个枚举a B × i a^{B \times i} a B × i ,查询m a p map m a p 或哈希表里面有没有。
思维比较简单,但是代码比较长。
时间复杂度O ( n ) O(\sqrt {n}) O ( n )
模板题:P2485 [SDOI2011]计算器
题解:
对于询问1. 1. 1 . ,快速幂即可。
对于询问2. 2. 2 . ,逆元即可,注意判断不存在的情况。(当然e x t g c d extgcd e x t g c d 也是可做的)
对于询问3. 3. 3 . ,需要运用B S G S BSGS B S G S 算法,具体实现时需要注意B × i − j B \times i-j B × i − j 可能为负,需要+ p +p + p 再取模,并且j = 0 j=0 j = 0 ,b × a j = b b \times a^j=b b × a j = b 也是合法的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 #include <bits/stdc++.h> #define int long long using namespace std;inline int read () { int x=0 ,f=1 ; char ch=getchar (); while (ch<'0' ||ch>'9' ){ if (ch=='-' ) f=-1 ; ch=getchar (); } while (ch>='0' &&ch<='9' ){ x=(x<<3 )+(x<<1 )+(ch^'0' ); ch=getchar (); } return x*f; } int p;inline int ksm (int b,int k) { int ans=1 ; while (k){ if (k&1 ) ans=(ans*b)%p; b=(b*b)%p; k>>=1 ; } return ans; } inline void Solve1 (int T) { while (T--){ int y=read (),z=read ();p=read (); y%=p; printf ("%lld\n" ,ksm (y,z)); } } inline void Solve2 (int T) { while (T--){ int y=read (),z=read ();p=read (); y%=p,z%=p; if (y==0 &&z!=0 ){ printf ("Orz, I cannot find x!\n" ); continue ; } printf ("%lld\n" ,ksm (y,p-2 )*z%p); } } map<int ,int >M; inline void BSGS (int a,int b) { if (a==0 &&b!=0 ){ printf ("Orz, I cannot find x!\n" ); return ; } int B=(int )sqrt (p); M.clear (); int now=b%p; M[now]=0 ; for (register int i=1 ;i<=B;++i){ now=(now*a)%p; M[now]=i; } now=1 ; int S=ksm (a,B); for (register int j=1 ;j<=B;++j){ now=(now*S)%p; if (M.count (now)){ int ans=j*B-M[now]; printf ("%lld\n" ,(ans%p+p)%p); return ; } } printf ("Orz, I cannot find x!\n" ); } inline void Solve3 (int T) { while (T--){ int y=read (),z=read ();p=read (); BSGS (y%p,z); } } #undef int int main () {#define int long long int T=read (),K=read (); if (K==1 ) Solve1 (T); else if (K==2 ) Solve2 (T); else Solve3 (T); }
EXCRT 扩展中国剩余定理
在中国剩余定理的基础上,膜数p 1 , p 2 , p 3 . . . , p n p_1,p_2,p_3...,p_n p 1 , p 2 , p 3 . . . , p n 可能不是质数:
假设现在我们已经求出前k − 1 k-1 k − 1 个方程的解了,设为是x x x :
设M = l c m ( p 1 , p 2 , . . . . p k − 1 ) M=lcm(p_{1},p_{2},....p_{k-1}) M = l c m ( p 1 , p 2 , . . . . p k − 1 ) ,那么我们发现前k − 1 k-1 k − 1 个方程的通解可以表示成x + M × a l b x+M \times alb x + M × a l b (这些解都可以成立),其中a l b alb a l b 是整数。
我们要求t t t ,使得x + M × t = a k ( m o d p k ) x+M \times t=a_k (\mod p_k) x + M × t = a k ( m o d p k ) ,也就是M × t = a k − x ( m o d p k ) M \times t =a_k-x(\mod p_k) M × t = a k − x ( m o d p k )
可以用e x t g c d extgcd e x t g c d 求解t t t ,解完t t t 后,就发现前k k k 个式子的一个解为x + t × M x+t \times M x + t × M
整体思路也就是把式子合并合并再合并。
话说这个东西和C R T CRT C R T 关系好像不是很大。
高斯消元
可以求解类似于
a 11 × x + a 12 × y + a 13 × z . . . . . . . = b 1 a_{11} \times x + a_{12} \times y + a_{13} \times z ....... = b_1
a 1 1 × x + a 1 2 × y + a 1 3 × z . . . . . . . = b 1
a 21 × x + a 22 × y + a 23 × z . . . . . . . = b 2 a_{21} \times x + a_{22} \times y + a_{23} \times z ....... = b_2
a 2 1 × x + a 2 2 × y + a 2 3 × z . . . . . . . = b 2
a 31 × x + a 32 × y + a 33 × z . . . . . . . = b 3 a_{31} \times x + a_{32} \times y + a_{33} \times z ....... = b_3
a 3 1 × x + a 3 2 × y + a 3 3 × z . . . . . . . = b 3
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ........................................
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ........................................
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
的方程。
假设我们有三个式子,假设a l b alb a l b 为现在未知数个数,现在a l b alb a l b 为3 3 3 :
1 × x + 2 × y + 3 × z = 4... ( 1 ) 1 \times x + 2 \times y + 3 \times z = 4 ... (1)
1 × x + 2 × y + 3 × z = 4 . . . ( 1 )
2 × x + 3 × y + 4 × z = 5... ( 2 ) 2 \times x + 3 \times y + 4 \times z = 5 ... (2)
2 × x + 3 × y + 4 × z = 5 . . . ( 2 )
3 × x + 4 × y + 7 × z = 6... ( 3 ) 3 \times x + 4 \times y + 7 \times z = 6 ... (3)
3 × x + 4 × y + 7 × z = 6 . . . ( 3 )
我们把( 1 ) (1) ( 1 ) 中的x x x 设为主元,和( 2 ) ( 3 ) (2)(3) ( 2 ) ( 3 ) 式相减。
( 2 ) − ( 1 ) × 2 : − 1 × y + − 2 × z = − 3... ( 4 ) (2)-(1) \times 2 : -1 \times y + -2 \times z = -3 ... (4)
( 2 ) − ( 1 ) × 2 : − 1 × y + − 2 × z = − 3 . . . ( 4 )
( 3 ) − ( 1 ) × 3 : − 2 × y + − 2 × z = − 6... ( 5 ) (3)-(1) \times 3 : -2 \times y + -2 \times z = -6 ... (5)
( 3 ) − ( 1 ) × 3 : − 2 × y + − 2 × z = − 6 . . . ( 5 )
发现a l b = 2 alb=2 a l b = 2 ,继续执行一遍类似的操作,把( 4 ) (4) ( 4 ) 中的y y y 设为主元,和( 5 ) (5) ( 5 ) 式相减。
( 5 ) − ( 4 ) × 2 : 2 × z = 0 (5)-(4) \times 2 : 2 \times z = 0
( 5 ) − ( 4 ) × 2 : 2 × z = 0
我们就成功地解出了z z z ,把z z z 往上带,可以求出x x x ,y y y ,就可以解出方程。
不仅对于a l b = 3 alb=3 a l b = 3 的情况,a l b alb a l b 更大,也可以用类似的方法求出未知数。
时间复杂度O ( a l b 2 ) O(alb^2) O ( a l b 2 )
高斯消元的操作可以转换为矩阵操作,其实就是把一个普通矩阵转换为单位矩阵。
逆矩阵
单位矩阵e e e :只有主对角线为1 1 1 的矩阵
容易发现单位矩阵乘任意矩阵,任意矩阵乘单位矩阵都为其本身
于是定义一个n × n n\times n n × n 的矩阵A A A 的逆矩阵为A − 1 A^{-1} A − 1 满足A × A − 1 = e A \times A^{-1}=e A × A − 1 = e ;若B × A = C B \times A=C B × A = C ,则B = C ∗ A − 1 B=C*A^{-1} B = C ∗ A − 1
矩阵初等变换:交换两行/列,将一行/列的若干倍加到另一行/列上去(这些操作都可以通过左乘初等变换矩阵实现)
那么可以把A A A 搞成e e e 的变换矩阵就是A − 1 A^{-1} A − 1 了
过程就是高斯消元,开始在原矩阵的旁边维护一个e e e
对原矩阵的操作,都对这个矩阵也做一次
这样当A A A 变成e e e 了,原来的这个e e e 就变成A − 1 A^{-1} A − 1 了
我们可以把操作矩阵定义为C 1 , C 2 , . . . C k C_1,C_2,...C_k C 1 , C 2 , . . . C k ,发现A × C 1 × C 2 × C 3 . . . × C k = e A \times C_1 \times C_2 \times C_3 ... \times C_k=e A × C 1 × C 2 × C 3 . . . × C k = e ,
由于矩阵支持结合律,我们可以在这个式子两边同时乘以A − 1 A^{-1} A − 1 ,发现A × A − 1 × C 1 × C 2 × C 3 . . . × C k = e × A − 1 A \times A^{-1} \times C_1 \times C_2 \times C_3 ... \times C_k=e \times A^{-1} A × A − 1 × C 1 × C 2 × C 3 . . . × C k = e × A − 1
由于上面的两条性质A × A − 1 = e A \times A^{-1}=e A × A − 1 = e 和A × e = A A \times e = A A × e = A ,我们可以将式子化为e × C 1 × C 2 × C 3 . . . × C k = A − 1 e \times C_1 \times C_2 \times C_3 ... \times C_k = A^{-1} e × C 1 × C 2 × C 3 . . . × C k = A − 1
所以原来的e e e 就变为A − 1 A^{-1} A − 1 了,是不是很巧妙?
拉格朗日插值法
全然わからない!,似乎是一个构造函数的神奇方法,留个坑待填。
一道小水题 P4986