数学模板总结
好吧。不得不说数论的公式是真的多。
数论
一.同余
a≡b(mod c)a≡b(mod \ \ c)a≡b(mod c)成立的充要条件是(a−b)=k∗c(a-b)=k*c(a−b)=k∗c
二.GCD && LCM
$gcd(a,b)=gcd(b,a%b) $证明:唯一分解定理
ab=lcm(a,b)∗gcd(a,b)ab = lcm(a,b) * gcd(a,b)ab=lcm(a,b)∗gcd(a,b) 证明同上
int gcd(int a,int b){ return b ? gcd(b, a % b) : a;}
int lcm(int a,int b){ return a / gcd(a,b) * b;} //越界!
三.素数
线性筛素数
void make_prime(int m){
for(int i = 2; i <= m; ++i) {
if(!flag[i]) pri[++cnt] = i;
for(int j = 1; j <= cnt && pri[j] <= m / i; ++j){
flag[pri[j] * i] = 1;
if(i % pri[j] == 0) break;
}
}
}
四.快速幂
ll Power(ll x,ll y){
x %= P;ll ans = 1;
while(y){
if(y & 1) ans = (ans * x) % P;
x = (x * x) % P;
y >>= 1;
}
return ans;
}
五.拓展欧几里得
void exgcd(ll a,ll b,ll &x,ll &y){
if(!b){
x = 1;y = 0;d = a;
return;
}
exgcd(b,a % b,x,y);
ll t = y;
y = x - a / b * y;
x = t;
}
应用:
1、求解不定方程ax+by=cax+by=cax+by=c
方程有解的条件:gcd(a,b)∣cgcd(a,b) | cgcd(a,b)∣c
通解为:x=x0+bgcd∗k;y=y0−agcd∗k;x=x_{0}+\frac{b}{gcd}*k;y=y_{0}-\frac{a}{gcd}*k;x=x0+gcdb∗k;y=y0−gcda∗k;
2、求解线性同余方程 ax≡b(mod n)ax≡b(mod\ n)ax≡b(mod n)
方程等价于ax+ny=bax+ny=bax+ny=b
(1) 方程有解的条件:gcd(a,n)∣bgcd(a,n)|bgcd(a,n)∣b
(2) 方程ax≡b(mod n)ax≡b(mod \ \ n)ax≡b(mod n) 或者对模n有gcd(a,n)个不同的解(有解当且仅当gcd(a,n)|b),或者无解。
3、求解模的逆元
六.欧拉函数φ
对于正整数n,欧拉函数是指少于(或等于)n的数中与n互质的数的数目。
φ(x)=x(1−1/p1)(1−1/p2)(1−1/p3)(1−1/p4)…..(1−1/pn)φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn)φ(x)=x(1−1/p1)(1−1/p2)(1−1/p3)(1−1/p4)…..(1−1/pn)其中p1,p2……pnp1, p2……pnp1,p2……pn为xxx的所有质因数。(容斥原理)
性质:
(1)欧拉函数是积性函数。
对于定义域为N⁺N⁺N⁺的函数fff若任意两个互质的正整数a,ba,ba,b都满足f(ab)=f(a)∗f(b)f(ab) = f(a)*f(b)f(ab)=f(a)∗f(b)则f是积性函数。若任意两个a,b都满足f(ab)=f(a)∗f(b)f(ab) = f(a)*f(b)f(ab)=f(a)∗f(b)则f是完全积性函数。
(2) 若n是质数p的k次幂,φ(n)=pk−pk−1=(p−1)pk−1φ(n)=p^k-p^{k-1}=(p-1)p^{k-1}φ(n)=pk−pk−1=(p−1)pk−1
(3) 若p是质数:φ(p)=p−1φ(p) = p - 1φ(p)=p−1
(4) 如果i%p=0i\%p=0i%p=0, 那么φ(i∗p)=p∗φ(i)φ(i*p)=p*φ(i)φ(i∗p)=p∗φ(i)
(5) i%pi\%pi%p不为0且p为质数, 所以i与p互质, 那么根据积性函数的性质$ φ(i*p)=φ(i)*φ§$
(6) 与n互质的所有数的和sum=n∗φ(n)2;sum= \frac{n*φ(n)}{2};sum=2n∗φ(n);
$gcd(n,i)=1 则则则gcd(n,n-i)=1$
void phi_table(int m){
phi[1] = 1;
for(int i = 2; i <= m; ++i) {
if(!flg[i]) {pri[++cnt] = i;phi[i] = i - 1;}
for(int j = 1; j <= cnt && pri[j] <= m / i; ++j){
flg[i * pri[j]] = 1;
if(i % pri[j] == 0){
phi[i * pri[j]] = phi[i] * pri[j];
break;
}
else phi[i * pri[j]] = phi[i] * phi[j];//也可写成phi[i]*(pri[j]-1)
}
}
}
七.欧拉定理 && 费马小定理
欧拉定理:若a,n互质,则aφ(p)≡1 (mod p)a^{φ(p)}≡1 \ \ \ (mod \ \ p)aφ(p)≡1 (mod p)
费马小定理:a是不能被质数p整除的正整数,则有a(p−1)≡1(mod p)a^{(p-1)}≡1(mod\ \ p)a(p−1)≡1(mod p)
推论:对于任意正整数a,有ap≡a(mod p)a^p≡a(mod \ \ p)ap≡a(mod p),因为a能被p整除时结论显然成立。
八.矩阵乘法
满足结合律。
(AB)N=AN∗BN(AB)^N=A^N*B^N(AB)N=AN∗BN
inline matrix mul1(matrix A,matrix B){
matrix C;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
for(int k = 1; k <= n; ++k)
C.a[i][j] = (C.a[i][j] + A.a[i][k] * B.a[k][j]) % mod;
return C;
}
for(int i = 1; i <= n; ++i) E.a[i][i]=1;
九.乘法逆元ax≡1(mod p)ax≡1(mod \ \ p)ax≡1(mod p)
1.定义:如果A∗B %P=1A*B\ \ \%P=1A∗B %P=1,我们称B是A的逆元。
如果AAA是PPP的倍数就没有关于模PPP的逆元。由定义,AA%P=0A恒成立.
2.计算方式:
a) 拓展欧几里得
b) 费马小定理B=Power(A,mod−2)B = Power(A,mod - 2)B=Power(A,mod−2)
c) 线性求逆元
inv[1] = 1
inv[i] = (M - M / i) * inv[M % i]% M
//由t = M / i, k = M % i; t * i + k≡0 ;推知
当逆元不存在时:
采用变换模值法:(A/B) %mod=(A%(mod∗B))/B %mod(A/B)\ \ \%mod=(A\%(mod*B))/B\ \%mod(A/B) %mod=(A%(mod∗B))/B %mod。
对B∗modB*modB∗mod取余,剩余的值必定是B的倍数.适用于modmodmod和BBB较小的时候。
十.中国剩余定理及拓展
x=a1∗x1+b1x=a1*x1+b1x=a1∗x1+b1
x=a2∗x2+b2x=a2*x2+b2x=a2∗x2+b2
.........
x=an∗xn+bnx=an*xn+bnx=an∗xn+bn此处满足(x1,x2,x3...)(x1,x2,x3...)(x1,x2,x3...)互质
中国剩余定理的拓展
x=m1∗k1+c1①x = m1 * k1 + c1①x=m1∗k1+c1①
x=m2∗k2+c2x = m2 * k2 + c2x=m2∗k2+c2
a) m1∗k1+c1=m2∗k2+c2m1 * k1 + c1 = m2 * k2 + c2m1∗k1+c1=m2∗k2+c2
$m1 * k1 = c2 - c1 + m2 * k2 $ ②
b) 由贝祖定理,②有解⇔gcd(m1,m2)∣(c2−c1)⇔gcd(m1,m2)|(c2-c1)⇔gcd(m1,m2)∣(c2−c1)
c) ②两边同除gcd(m1,m2)gcd(m1,m2)gcd(m1,m2)
ll ex_ch_remainder(ll k){
ll m1,m2,c1,c2;
for(int i = 2; i <= k; ++i){
c1 = c[i - 1];c2 = c[i];m1 = m[i - 1];m2 = m[i];
ll d = exgcd(m1,m2);
if((c2 - c1) % d) return -1;
m[i] = m1 * m2 / d;
c[i] = inv(m1 / d,m2 / d) * ((c2 - c1) / d) % (m2 / d) * m1 + c1;
c[i] = ((c[i] % m[i]) + m[i]) % m[i];
}
return c[k];
}
十一.BSGS及拓展BSGS(思想:meet in the middle)
用于求解高次同余方程: ax≡b(modc)a^{x}≡b (mod c)ax≡b(modc)
$x = i * m - j; \ \ m = ceil(sqrt©); 先计算先计算先计算b * a ^{j}$
map <ll,int> mp;
ll BSGS(ll a,ll b,ll p){
if(exgcd(a,p) != 1) return -inf;
mp.clear();
ll m = ceil(sqrt(p)); ll t = b % p;
mp[t] = 0;
for(int i = 1; i <= m; ++i){
t = (t * a) % p;
mp[t] = i;
}
t = t * inv(b,p) % p;
ll tmp = 1;
for(int i = 1; i <= m; ++i){
tmp = (tmp * t) % p;
if(mp[tmp]) return ((i * m - mp[tmp]) % p + p) % p;
}
return -inf;
}
ll ex_BSGS(ll a,ll b,ll c){
ll d = 1,t,cnt = 0;
while((t = exgcd(a,c)) != 1){
if(b % t) return -1;
b /= t; c /= t;
d = d * a / t % c;
cnt++;
if(d == b) return cnt;
}
b = b * inv(d,c) % c;
return BSGS(a,b,c) + cnt;
}
十二.原根与阶
设m>1m>1m>1,gcd(a,m)=1gcd(a,m)=1gcd(a,m)=1,使得aˣ≡1(mod m)aˣ≡1(mod \ \ m)aˣ≡1(mod m)成立的最小的rrr,称为aaa对模mmm的阶。
十三.其他定理
1.费马平方和定理 : 一个奇素数p能表示为两个数的平方和,那么这个奇素数一定是4k+1型的。
if P=a2+b2 then P=4k+1if \ \ P =a^2+b^2 \ \ then\ \ P = 4k + 1if P=a2+b2 then P=4k+1
2.指数循环定理:ab≡ab%φ(p)+φ(p)(mod p)a^b ≡ a^{b \% φ(p)+φ(p)} (mod\ \ p)ab≡ab%φ(p)+φ(p)(mod p)
用于bbb远大于φ(p)φ(p)φ(p)时
3.约数和公式:
对于已经分解的整数A=(p1k1)∗(p2k2)∗(p3k3)∗....∗(pnkn)A=(p_{1}^{k_{1}})*(p_{2}^{k_{2}})*(p_{3}^{k_{3}})*....*(p_{n}^{k_{n}})A=(p1k1)∗(p2k2)∗(p3k3)∗....∗(pnkn)
有A的所有因子之和为
S=(1+p1+p12+p13+...p1k1)∗(1+p2+p22+p23+...p2k2)∗...∗(1+pn+pn2+pn3+...pnkn)S=(1+p_{1}+p{1}^2+p_{1}^3+...p_{1}^{k_{1}})*(1+p_{2}+p_{2}^2+p_{2}^3+...p_{2}^{k_{2}})*...\\
*(1+p_{n}+p_{n}^2+p_{n}^3+...p_{n}^{k_{n}})S=(1+p1+p12+p13+...p1k1)∗(1+p2+p22+p23+...p2k2)∗...∗(1+pn+pn2+pn3+...pnkn)
4.约数个数定理:
X=p1k1∗p2k2∗p3k3∗p4k4...pnknX=p_1^{k_1}*p_2^{k_2}*p_3^{k_3}*p_4^{k_4}...p_n^{k_n}X=p1k1∗p2k2∗p3k3∗p4k4...pnkn
X的约数个数为:
Y=(1+k1)(1+k2)(1+k3)...(1+kn)Y=(1+k_1)(1+k_2)(1+k_3)...(1+k_n)Y=(1+k1)(1+k2)(1+k3)...(1+kn)
5.反素数:
当需要枚举较多数的质因子或枚举具有特定约数个数的数时可以反其道而行之,不正向分解而是直接枚举因子从最小的素数2开始枚举,枚举因子中包含0个2、1个2、2个2…k个2,直至m∗2km*2^km∗2k大于区间的上限N。在这个基础上枚举3、5、7……的情况。
6.康托展开
以 1 2 3 4 四个数为例
是 1234 的全排列 的第几个,康托展开值就是多少。
1234 0
1243 1
1324 2
1342 3
1423 4
1432 5
2134 6
······
计算方法:
X=a[n]∗(n−1)!+a[n−1]∗(n−2)!+...+a[i]∗(i−1)!+...+a[1]∗0!;X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0!;X=a[n]∗(n−1)!+a[n−1]∗(n−2)!+...+a[i]∗(i−1)!+...+a[1]∗0!;
n代表这个数的第n位
其中a[i]为当前未出现的元素中是排在第几个(从0开始),并且0<=a[i]< i(1<=i<=n)
6.康托逆展开:
http://blog.csdn.net/lttree/article/details/24798653
{1,2,3,4,5}的全排列,并且已经从小到大排序完毕
(1)找出第96个数
首先用96-1得到95
用95去除4! 得到3余23
有3个数比它小的数是4
所以第一位是4
用23去除3! 得到3余5
有3个数比它小的数是4但4已经在之前出现过了所以第二位是5(4在之前出现过,所以实际比5小的数是3个)
用5去除2!得到2余1
有2个数比它小的数是3,第三位是3
用1去除1!得到1余0
有1个数比它小的数是2,第二位是2
最后一个数只能是1
所以这个数是45321
(2)找出第16个数
首先用16-1得到15
用15去除4!得到0余15
用15去除3!得到2余3
用3去除2!得到1余1
用1去除1!得到1余0
有0个数比它小的数是1
有2个数比它小的数是3 但由于1已经在之前出现过了所以是4(因为1在之前出现过了所以实际比4小的数是2)
有1个数比它小的数是2 但由于1已经在之前出现过了所以是3(因为1在之前出现过了所以实际比3小的数是1)
有1个数比它小得数是2 但由于1,3,4已经在之前出现过了所以是5(因为1,3,4在之前出现过了所以实际比5小的数是1)
最后一个数只能是2
所以这个数是14352
我们可以用数据结构维护第K大,找出第K大后将它删除。
7.求N的第k大的因子 N\sqrt NN直接枚举就好。
8.分解质因数:
while(n != 1 && pri[i] <= t && i <= cnt){//!! i<=cnt
if(n % pri[i] == 0){
++pos;
while(n % pri[i] == 0){
n /= pri[i];
num[pos] += 1;
}
}
++i;//!!一定要加
}
排列组合
A(n,m)=n!(n−m)!A(n,m) = \frac{n!}{(n - m)!}A(n,m)=(n−m)!n!
C(n,m)=n!(n−m)!m!C(n,m) = \frac{n!}{(n - m)!m!}C(n,m)=(n−m)!m!n!
基本定理:
C(n,0)∗C(n,1)∗...∗C(n,n)=2nC(n,0)* C(n,1)*...*C(n,n) = 2 ^ nC(n,0)∗C(n,1)∗...∗C(n,n)=2n
C(n,r)+C(n,r+1)=C(n+1,r+1)C(n,r) + C(n,r + 1) = C(n + 1,r + 1)C(n,r)+C(n,r+1)=C(n+1,r+1)
C(n,0)=1C(n,0) = 1C(n,0)=1
C(n,i)=C(n,i−1)∗(n−i+1)/iC(n,i) = C(n,i - 1) * (n - i + 1) / iC(n,i)=C(n,i−1)∗(n−i+1)/i
D(1)=0;D(n)=(n−1)∗(D(n−1)+D(n−2))D(1) = 0;D(n) = (n - 1) * (D(n - 1) + D(n - 2))D(1)=0;D(n)=(n−1)∗(D(n−1)+D(n−2)) 错排
基本模型:
隔板法
x1+x2+..+xm=n(xi>0)x1 + x2 + .. + xm = n(xi > 0)x1+x2+..+xm=n(xi>0)问解数
C(n−1,m−1)C(n - 1, m - 1)C(n−1,m−1)
x1+x2+..+xm=n(xi>=0)x1 + x2 + .. + xm = n(xi>=0)x1+x2+..+xm=n(xi>=0)问解数
C(n+m−1,m−1)C(n + m - 1, m - 1)C(n+m−1,m−1)
x1+x2+..+xm<=n(xi>0)x1 + x2 + .. + xm <= n(xi>0)x1+x2+..+xm<=n(xi>0)问解数
等价于(x0>=0)x0+x1+x2+..+xm=n(x_{0}>=0)x0 + x1 + x2 + .. + xm = n(x0>=0)x0+x1+x2+..+xm=n
C(n,m)C(n, m)C(n,m)
x1+x2+..+xm=n(0<xi<=ai)x1 + x2 + .. + xm = n(0 < xi <= ai)x1+x2+..+xm=n(0<xi<=ai)问解数
其它定理:
- lucas:大组合数取模
ll C(ll a,ll b){
if(b > a) return 0;
b = min(b,a - b);
ll up = 1,down = 1;
for(int i = 0 ; i < b; ++i) {
up = up * (a - i) % mod;
down = down * (i + 1) % mod;
}
return up * mul(down,mod - 2) % mod;
}//神速 (一乘一除最快最省事)
ll lucas(ll a,ll b){
if(!b) return 1;
return C(a % mod,b % mod) * lucas(a / mod,b / mod) % mod;
}
1079

被折叠的 条评论
为什么被折叠?



