模板及讲解
欧几里得算法
求gcd(a, b),即a和b的最大公倍数
欧几里得算法:
int gcd(int a, int b)
{
if (b==0) return a;
gcd(b, a%b);
}
求ax+by=gcd(a,b)的解x,y
扩展欧几里得算法:
已求出下一个状态一组解x1,y1使得b⋅x1+(a%b)⋅y1=gcd(a,b)
由a%b=a−⌊ab⌋⋅b,得
b⋅x1+(a−⌊ab⌋⋅b)⋅y1=gcd(a,b)
b⋅x1+a⋅y1−b⋅y1⋅⌊ab⌋=gcd(a,b)
a⋅y1+b⋅(x1−y1⋅⌊ab⌋)=gcd(a,b)
对照ax+by=gcd(a,b),可得
x=y1,y=x1−y1⋅⌊ab⌋
由欧几里得算法终止条件a=gcd(a,b),b=0得,a∗1+b∗0=gcd(a,b)
所以x,y的边界值是1,0
通解:
int egcd(int a, int b, int &x, int &y)
{
if (b==0)
{
x = 1;
y = 0;//边界值
return a;//求最大公倍数
}
int temp = x;
int ans = egcd(b,a%b,x,y);
x = y;
y = temp-y*a/b;//公式计算
return ans;
}
求不定方程ax+by=c的最小一组解x,y:
先求出g=gcd(a,b)
如果c%g≠0,无解
否则,将不定方程两边同时除以g,得
此时gcd(a1,b1)=1,可用扩展欧几里得算法求出a1x1+b1y1=1的解x1,y1
即a1x+b1y=c1的一组解为x1⋅c1,y1⋅c1
求最小解可用一组特解模b即可得到
求a 关于 m 的乘法逆元
由同余性质得,ax−1=ny
变形,得 ax−ny=1,此时gcd(a,n)必须为1且只有唯一解, 否则无解
即可使用扩展欧几里得算法求解
中国剩余定理
设正整数
有整数解。并且在模M=m1⋅m2⋅...⋅mk下有唯一解,
解为
其中Mi=Mmi,M−1i是Mi模mi下的逆元
解法:先O(n)的时间求出M,然后求出
int crt(int n, int *a, int *m)
{
int ans = 0;
int M = 1;
for (int i=1;i<=n;i++) M *= m[i];
for (int i=1;i<=n;i++)
{
int Mi = M/m[i];
int x,y;
e_gcd(Mi, m[i], x, y);//求Mi的逆元x
ans = (ans + a[i]*Mi*x)%M;
}
return (ans+M)%M;
}
筛选法求质数
int vis[n];
int sx()
{
int m = sqrt(n+0.5);
ms(vis,0);
for (int i=2;i<=n;i++)
if (!vis[i]) for (int j=i*i;j<=n;j+=i) vis[j] = 1;
}
欧拉函数
给出n的唯一分解式 n=pa11pa22pa33...pakk , 求出 1,2,3...,n 中与n互素的数的个数
公式(容斥原理):
可变形为:
即可在O(k)的时间复杂度算出φ(n)
不给出唯一分解式求φ(n):
根据变形的公式,可以枚举所有小于n√的因子,然后之后把他”除干净”即可
int phi(int n)
{
int ans = n;//ans为最后的答案
int m = (int)sqrt(n+0.5);
for (int i=2;i<=m;i++) if (n%i==0)
{
ans = ans/i*(i-1);//ans初值为n,因为1-(1/p) = (p-1)/p,由变形后公式可得
while (n%i==0) n/=i;//除干净
}
if (n>1) ans = ans/n*(n-1);
return ans;
}
用筛选法在O(nloglogn)时间复杂度求1~n中所有数的欧拉phi函数值:
int phitable(int n, int* phi)
{
for (int i=2;i<=n;i++) phi[i] = 0;
phi[1] = 1;
for (int i=2;i<=n;i++) if (!phi[i])
for (int j=i;j<=n;j+=i)
{
if (!phi[j]) phi[j] = j;
phi[j] = phi[j]/i*(i-1);
}
}
求正约数的个数
给出n的唯一分解式 n=pa11pa22pa33...pakk , 求出 n 的正约数的个数
根据乘法原理,
快速幂
int fastpow(int a,int b)
{
int ans=1,base=a;
while(b!=0){
if(b&1!=0)
ans*=base;
base*=base;
b>>=1;
}
return ans;
}
排列
一般地,从n个不同元素中取出
(约定0!=1)
1 无重排列
从n个不同元素中有序且不重复取出
2 全排列
(1) 无重
当k-排列中的k=n时
3 重复排列
从n个不同元素中有序且可重复取出
重复排列个数为
4 圆周排列
从n个不同元素中无重复地取出
圆周排列个数为
组合
一般地,从n个不同元素中取出
(约定0!=1)
1 无重组合
从n个不同元素中无序且不重复取出
2 重复组合
从n个不同元素中无序但可重复取出
重复组合个数为
概率
1 数学期望
随机变量X的数学期望