【数论】gcd|扩展gcd|素数筛法|快速幂|欧拉函数(各种模板)
2017-03-15 14:08
435 查看
这里总结了一些基础的数学概念。
整除:
一个数可以被另一个数整除是数论中的一个关键概念。d|a(d整除a,a除以d)的含义是存在某个整数k,使得a=kd。称a是d的倍数,d是a的约数(因数)。
带余数除法:
a、b为两个正整数,且b≠,0,则存在唯一整数q和r,使得a=qb+r,0<=r<b,则有r=a mod b。例如10 mod 2=0,7 mod 3=1。可以用来判断一个正数是奇数还是偶数,如当n%2得到的余数是0,则n为偶数,如果n%2得到的余数是1,则n为奇数。
关于d|b的一些推论
① d|a且d|b,则d|(a+b)且d|(a-b)
② d|a且d|b,则d|(ax+by)
③ a|b且b|a,则a=±b
最大公约数:
一般用gcd(a,b)来表示a和b的最大公约数。并且对于任意非负整数a和任意正整数b,有gcd(a,b)=gcd(b,a mod b),证明略。
用代码求最大公约数:
关于最大公约数的一些推论:
① 对于ax+by(x,y∈Z)的线性组合集,gcd(a,b)是这个集合中的最小正整数。
② d|a且d|b,则d|gcd(a,b)
③ 对于n,a,b∈N+,如果n|ab,且gcd(a,n)=1,则n|b
互质数:
对于两个整数a和b,如果gcd(a,b)=1,则称a和b为互质数。等价于ax+by=1
唯一因子分解定理:
合数a仅能以一种方式写成如下乘积形式a=p1^e1*p2^e2*p3^e3……*pn^en,其中pi为素数,ei均为正整数。
扩展gcd算法:
该算法用来求解形如ax+by=c的通解。我们知道了ax+by=gcd(a,b)的方程肯定存在解,只要我们找到一组特殊的解x0和y0,便可以通过x=x0+(b/gcd(a,b))*t,y=y0-(a/gcd(a,b))*t。
考虑当前状态和下一个状态,有ax+by=gcd(a,b)=gcd(b,a%b)=bx1+(a%b)y1=bx1+(a-(a/b)*b)y1=ay1+b(x1-a/b*y1)。
前后式子对比,可得x=y1,y=x1-a/b*y1;
扩展gcd的三个应用:
① 求解不定方程
形如ax+by=c的不定方程,若c mod gcd(a,b)=0,则该方程存在整数解,否则不存在。
② 求解模线性方程(线性同余方程)
同余方程ax≡b(mod n)(即ax和b关于n同余 b)对于未知数x有解,当且仅当gcd(a,n)|b。且当方程有解时,方程有gcd(a,n)个解。
对于该同余方程,相当于求解ax+ny=b。
证明:设d=gcd(a,n),则ax+ny=d.如果d|b,则ax0+ny0=d,同乘b/d得ax0*b/d+ny0*b/d=b。所以x=x0*b/d,y=y0*b/d为ax+ny=d的一个解,即x=x0*b/d为ax≡b(mod n)的解。且方程的 d个解分别为 xi= (x0+ i* (n/ d ))mod n {i= 0... d-1}。
设ans=x*(b/d),s=n/d;方程ax≡b (mod n)的最小整数解为:(ans%s+s)%s;
③ 求解模的逆元
当ax≡b(mod n)的gcd(a,n)=1时,方程只有唯一解。如果b=1,则x是a对模n的乘法逆元。即对于任意ax≡1(mod n),如果gcd(a,n)=1,那么方程ax≡1(mod n)对模n有唯一解,否则无解。解方程组ax+ny=1,求得x即为逆元。
中国剩余定理:
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?翻译过来就是有一个数x,x%3=2,x%5=3,x%7=2,求x。中国剩余定理便用来解决这一类问题。
(设m1,m2,···,mk两两互素)
x=a1(mod m1);
x=a2(mod m2);
···
x=ak(mod mk);
其在M=m1*m2*···*mk;中有唯一整数解。
记Mi=M/mi;因为gcd(Mi,mi)=1,故有两整数pi,qi满足Mi*pi+mi*qi=1,如果记ei=Mi*pi;那么:ei=0 (mod mj),j!=i;ei=1(mod mj),j=i;
很明显,e1*a1+e2*a2+···+ek*ak就是方程的一个解,加减M倍后就可以得到最小非负整数解了。
如果m1,m2,···,mk不互素,那只能两个两个求了。
x=a1 (mod m1);
x=a2 (mod m2);
解完后,a=x; m=m1和m2的最小公倍数。即可。
以下代码中a数组是除数,b数组是余数
素数筛法:Eratosthenes 筛选
因式分解:将数分解为唯一因子分解定理中的形式。
二分快速幂:
求解a的b次方,我们可以通过将b看成二进制来加速a的b次方的求解,比如a的17次方,可以看成是a^1*a^16,而a^16=a^8*2=a^4*2*2=a^2*2*2*2=a*2*2*2*2,只需要5次运算。通常计算a^b伴随着取模,即a^b%c,代码如下
排列组合:
排列:从n个不同元素中取出m个的排列数。A(n,m)=n!/(n-m)!
组合:从n个不同元素中取出m个的组合数。C(n,m)=A(n,m)/m!=(n!)/(m!(n-m)!)
组合数的性质
① C(n,m)=C(n,n-m),从n个里面选m个的方案数和从n个里面选n-m个的方案数相同。
② C(n,m)=C(n-1,m)+C(n-1,m-1),从n个里面选m个的方案等于从n-1个里面选出m个的方案(不选第n个)加上从n-1个里面选出m-1个的方案(选第n个)。
可以发现性质2刚好是杨辉三角(递推式为F[i][j]=F[i-1][j]+F[i-1][j-1]),因此我们可以通过这种方式求出组合数。
矩阵快速幂:快速求矩阵的n次方
欧拉函数
对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目。例如euler(8)=4,因为1,3,5,7均和8互质。
Euler函数表达通式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数,x是不为0的整数。euler(1)=1(唯一和1互质的数就是1本身)。
欧拉公式的延伸:一个数的所有质因子之和是euler(n)*n/2。
//直接求解欧拉函数
筛选法求欧拉函数,时间复杂度O(nloglogn)
欧拉定理:
欧拉定理表明,若n,a为正整数,且n,a互质,(a,n) = 1,则a^φ(n) ≡ 1 (mod n)
费马小定理:
假如p是质数,且a,p互质,那么 a的(p-1)次方除以p的余数恒等于1 。gdc(a,p)=1,那么a^(p-1) ≡1(mod p)
整除:
一个数可以被另一个数整除是数论中的一个关键概念。d|a(d整除a,a除以d)的含义是存在某个整数k,使得a=kd。称a是d的倍数,d是a的约数(因数)。
带余数除法:
a、b为两个正整数,且b≠,0,则存在唯一整数q和r,使得a=qb+r,0<=r<b,则有r=a mod b。例如10 mod 2=0,7 mod 3=1。可以用来判断一个正数是奇数还是偶数,如当n%2得到的余数是0,则n为偶数,如果n%2得到的余数是1,则n为奇数。
关于d|b的一些推论
① d|a且d|b,则d|(a+b)且d|(a-b)
② d|a且d|b,则d|(ax+by)
③ a|b且b|a,则a=±b
最大公约数:
一般用gcd(a,b)来表示a和b的最大公约数。并且对于任意非负整数a和任意正整数b,有gcd(a,b)=gcd(b,a mod b),证明略。
用代码求最大公约数:
int gcd(int a,int b)//保证a>b { return b?gcd(b,a%b):a; }
关于最大公约数的一些推论:
① 对于ax+by(x,y∈Z)的线性组合集,gcd(a,b)是这个集合中的最小正整数。
② d|a且d|b,则d|gcd(a,b)
③ 对于n,a,b∈N+,如果n|ab,且gcd(a,n)=1,则n|b
互质数:
对于两个整数a和b,如果gcd(a,b)=1,则称a和b为互质数。等价于ax+by=1
唯一因子分解定理:
合数a仅能以一种方式写成如下乘积形式a=p1^e1*p2^e2*p3^e3……*pn^en,其中pi为素数,ei均为正整数。
扩展gcd算法:
该算法用来求解形如ax+by=c的通解。我们知道了ax+by=gcd(a,b)的方程肯定存在解,只要我们找到一组特殊的解x0和y0,便可以通过x=x0+(b/gcd(a,b))*t,y=y0-(a/gcd(a,b))*t。
考虑当前状态和下一个状态,有ax+by=gcd(a,b)=gcd(b,a%b)=bx1+(a%b)y1=bx1+(a-(a/b)*b)y1=ay1+b(x1-a/b*y1)。
前后式子对比,可得x=y1,y=x1-a/b*y1;
int e_gcd(int a,int b,int &x,int&y) { if(b==0){x=1;y=0;return a;} int ans=e_gcd(b,a%b,x,y); int temp=x; x=y; y=temp-a/b*y; return ans; }
扩展gcd的三个应用:
① 求解不定方程
形如ax+by=c的不定方程,若c mod gcd(a,b)=0,则该方程存在整数解,否则不存在。
② 求解模线性方程(线性同余方程)
同余方程ax≡b(mod n)(即ax和b关于n同余 b)对于未知数x有解,当且仅当gcd(a,n)|b。且当方程有解时,方程有gcd(a,n)个解。
对于该同余方程,相当于求解ax+ny=b。
证明:设d=gcd(a,n),则ax+ny=d.如果d|b,则ax0+ny0=d,同乘b/d得ax0*b/d+ny0*b/d=b。所以x=x0*b/d,y=y0*b/d为ax+ny=d的一个解,即x=x0*b/d为ax≡b(mod n)的解。且方程的 d个解分别为 xi= (x0+ i* (n/ d ))mod n {i= 0... d-1}。
设ans=x*(b/d),s=n/d;方程ax≡b (mod n)的最小整数解为:(ans%s+s)%s;
boolmodular_linear_equation(int a,int b,int n) { int x,y,x0,i; int d=exgcd(a,n,x,y); if(b%d) return false; x0=x*(b/d)%n; //特解 for(i=1;i<d;i++) printf("%d\n",(x0+i*(n/d))%n); return true; }
③ 求解模的逆元
当ax≡b(mod n)的gcd(a,n)=1时,方程只有唯一解。如果b=1,则x是a对模n的乘法逆元。即对于任意ax≡1(mod n),如果gcd(a,n)=1,那么方程ax≡1(mod n)对模n有唯一解,否则无解。解方程组ax+ny=1,求得x即为逆元。
int cal(int a,int m) { intx,y; intgcd=e_gcd(a,m,x,y); if(1%gcd!=0)return -1; x*=1/gcd; m=abs(m); inans=x%m; if(ans<0)ans+=m; returnans; }
中国剩余定理:
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?翻译过来就是有一个数x,x%3=2,x%5=3,x%7=2,求x。中国剩余定理便用来解决这一类问题。
(设m1,m2,···,mk两两互素)
x=a1(mod m1);
x=a2(mod m2);
···
x=ak(mod mk);
其在M=m1*m2*···*mk;中有唯一整数解。
记Mi=M/mi;因为gcd(Mi,mi)=1,故有两整数pi,qi满足Mi*pi+mi*qi=1,如果记ei=Mi*pi;那么:ei=0 (mod mj),j!=i;ei=1(mod mj),j=i;
很明显,e1*a1+e2*a2+···+ek*ak就是方程的一个解,加减M倍后就可以得到最小非负整数解了。
如果m1,m2,···,mk不互素,那只能两个两个求了。
x=a1 (mod m1);
x=a2 (mod m2);
解完后,a=x; m=m1和m2的最小公倍数。即可。
以下代码中a数组是除数,b数组是余数
int main() { double a[8], b[8], c[8], flag, max; int i, k; double answer = 0, plus = 1, j; for(i = 0; i < 8; i ++) { scanf("%lf", &a[i]); plus *=a[i]; } for(i = 0; i < 8; i ++) scanf("%lf", &b[i]); max = a[0]; for(i = 0; i < 8;i ++) { max = max < a[i]? a[i]:max; for(j = 1; ; j ++) { flag=j * plus/a[i]; if(fmod(flag , a[i]) == b[i]) break;//fmod(x,y)计算x/y的余数,返回x-n*y,用来计算浮点类型的 } c[i] = flag; answer += c[i]; } j=fmod(answer, plus); if(j < max) j +=plus; printf("%.0lf\n", j); return 0; }
素数筛法:Eratosthenes 筛选
for(int i=2;i<=n;i++) is_prime[i]=1; for(int i=2;i<=n;i++) { if(is_prime[i]) for(intj=i*I;i<=n;i++) is_prime[j]=0; }
因式分解:将数分解为唯一因子分解定理中的形式。
long long factor[100][2]; int facCnt; int getFactors(long long x)//把x进行素数分解 { facCnt=0; long long tmp=x; for(int i=1;prime[i]<=tmp/prime[i];i++) { factor[facCnt][1]=0; if(tmp%prime[i]==0) { factor[facCnt][0]=prime[i]; while(tmp%prime[i]==0) { factor[facCnt][1]++; tmp/=prime[i]; } facCnt++; } } if(tmp!=1) { factor[facCnt][0]=tmp; factor[facCnt++][1]=1; } return facCnt; }
二分快速幂:
求解a的b次方,我们可以通过将b看成二进制来加速a的b次方的求解,比如a的17次方,可以看成是a^1*a^16,而a^16=a^8*2=a^4*2*2=a^2*2*2*2=a*2*2*2*2,只需要5次运算。通常计算a^b伴随着取模,即a^b%c,代码如下
int pow_mod(int a,int b,int mod) { intres=1,temp=a; for(;b;b/=2) { if(b&1)res=res*temp%mod;//二进制上这一位为1,乘上这一位权值 temp=temp*temp%mod; } return res; }
排列组合:
排列:从n个不同元素中取出m个的排列数。A(n,m)=n!/(n-m)!
组合:从n个不同元素中取出m个的组合数。C(n,m)=A(n,m)/m!=(n!)/(m!(n-m)!)
组合数的性质
① C(n,m)=C(n,n-m),从n个里面选m个的方案数和从n个里面选n-m个的方案数相同。
② C(n,m)=C(n-1,m)+C(n-1,m-1),从n个里面选m个的方案等于从n-1个里面选出m个的方案(不选第n个)加上从n-1个里面选出m-1个的方案(选第n个)。
可以发现性质2刚好是杨辉三角(递推式为F[i][j]=F[i-1][j]+F[i-1][j-1]),因此我们可以通过这种方式求出组合数。
矩阵快速幂:快速求矩阵的n次方
struct matrix{ intn,m; lla[5][5]; }; matrix matrix_mul(matrix A,matrix B,intmod) { matrixC; C.n=A.n; C.m=B.m; for(inti=0;i<A.n;i++) { for(intj=0;j<B.m;j++) { C.a[i][j]=0; for(intk=0;k<A.m;k++) { C.a[i][j]+=A.a[i][k]*B.a[k][j]%mod; C.a[i][j]%=mod; } } } return C; } matrix unit() { matrix res; res.n=2; res.m=2; for(inti=0;i<res.n;i++) { for(intj=0;j<res.m;j++) { if(i==j) res.a[i][j]=1; else res.a[i][j]=0; } } return res; } matrix matrix_pow(matrix A,ll n,ll mod) { matrix res=unit(),temp=A; for(;n;n/=2) { if(n&1)res=matrix_mul(res,temp,mod); temp=matrix_mul(temp,temp,mod); } return res; }
欧拉函数
对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目。例如euler(8)=4,因为1,3,5,7均和8互质。
Euler函数表达通式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数,x是不为0的整数。euler(1)=1(唯一和1互质的数就是1本身)。
欧拉公式的延伸:一个数的所有质因子之和是euler(n)*n/2。
//直接求解欧拉函数
int euler(int n){ //返回euler(n) int res=n,a=n; for(int i=2;i*i<=a;i++){ if(a%i==0){ res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出 while(a%i==0) a/=i; } } if(a>1) res=res/a*(a-1); return res; }
筛选法求欧拉函数,时间复杂度O(nloglogn)
void init() { int i, j; memset(phi, 0, sizeof(phi)); phi[1] = 1; for(int i = 2; i < SIZE; i++) if(!phi[i]) { for(j = i; j < SIZE; j+=i) { if(!phi[j]) phi[j] = j; phi[j] = phi[j] / i * (i-1); } } return ; }
欧拉定理:
欧拉定理表明,若n,a为正整数,且n,a互质,(a,n) = 1,则a^φ(n) ≡ 1 (mod n)
费马小定理:
假如p是质数,且a,p互质,那么 a的(p-1)次方除以p的余数恒等于1 。gdc(a,p)=1,那么a^(p-1) ≡1(mod p)
相关文章推荐
- 数论快速入门(同余、扩展欧几里德、中国剩余定理、大素数测定和整数分解、素数三种筛法、欧拉函数以及各种模板)
- hdu1695 综合数论 欧拉函数 分解质因子 容斥原理 打印素数表 各种模板
- 四一。 数论 。4.19(gcd 扩展gcd,素数 ,快速幂)
- GCD 扩展GCD 快速GCD 模线性方程 模线性方程组 单独求欧拉函数 递推求欧拉函数
- 扩展欧几里得、求乘法逆元及其应用、中国剩余定理(互质版和非互质版)、欧拉函数、快速判素数模板
- POJ 3696 : The Luckiest number - 欧拉函数,快速幂[数论好题]
- poj3696 快速幂的优化+欧拉函数+gcd的优化+互质
- 【hdu - 1787 GCD Again (数论、欧拉函数)】
- uva 11424 && 11426 GCD - Extreme(数论:欧拉函数)
- 数论 - 欧拉函数模板题 --- poj 2407 : Relatives
- poj 3358 Period of an Infinite Binary Expansion(数论:欧拉函数+快速幂取模)
- HDU1695-GCD(数论-欧拉函数-容斥)
- GCD nyoj1007(欧拉函数运用&&数论入门)
- hdu 2462(数论:欧拉定理+快速幂取模优化+欧拉函数)
- FZU 1969 数论 GCD+欧拉函数应用
- 快速切题 sgu102.Coprimes 欧拉函数 模板程度 难度:0
- 1061 青蛙的约会 数论 扩展GCD
- 快速扩展ArcServer(ADF for DOT NET )自带模板
- poj 1845 Sumdiv(数论:欧拉函数+二分求等比数列前n项和+快速幂取模)
- 【数论】【筛法求素数】【欧拉函数】bzoj2818 Gcd