1)欧几里得算法(辗转相除法)
代码
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
说明
gcd(a,b)是计算自然数a和b的最大公约数的函数,
a=bxp+q,所以gcd(b,q)既整除a又整除b,也就整除gcd(a,b)。
反之,由于q=a-bxp,同理可证gcd(a,b)既整除b又整除q,也就整除gcd(b,q)
综上所述可知gcd(a,b)=gcd(b,q)=gcd(b,a%b)
不断这样操作下去,由于gcd的第二个参数总是不断减少的,最后会得到gcd(a,b)=gcd(c,0),而0和c的最大公约数是c,所以gcd(c,0)=c
当然了,我们需要保证gcd()函数的参数中,a>b
2)唯一分解定理
一个数n肯定能被分解成若干个素数(质数)相乘的形式:n=p1a1*p2a2 …pnan
那么:
- 数n的因子个数:(1+a1)(1+a2)……*(1+an)
- 所有因子之和:(q10+q11+q12…q1a1)(q20+q21+q22…q2a2)…*(qn0+qn1+qn2…qnan)
- 设两个整数的最小公倍数为
lcm(a,b)
a=p1e1p2e2…pnen
b=p1f1p2f2…pnfn
gcd(a,b)
=p1min{e1,f1}p2min{e2,f2}…pnmin{en,fn}
lcm(a,b)
=p1max{e1,f1}p2max{e2,f2}…pnmax{en,fn}
综上可知:lcm(a,b)*gcd(a,b)=ab
3)扩展欧几里得算法
直线上的点。求直线ax+by+c=0上有多少个整点(x,y)满足x∈[x1,x2],y∈[y1,y2]
找出一对整数(x,y)使得ax+by=gcd(a,b)
void gcd(int a,int b,int &d,int &x,int &y){
if(!b) {
d=a;x=1;y=0;
}
else{
gcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
由扩展欧几里得算法可知:
1)设a,b,c为任意整数。若方程ax+by=c的一组整数解为(x0,y0),则它的任意整数解都可以写成(x0+kb’,y0-ka’),其中a’=a/gcd(a,b),b’=b/gcd(a,b),k取任意整数。
2)设a,b,c为任意整数,g=gcd(a,b),方程ax+by=g的一组解是(a0,b0),则当c是g的倍数时ax+by=c的一组解是(x0c/g,y0c/g);当c不是g的整数时无整数解。
4)同余和模运算
(a+b)mod n=((a mod n)+(b mod n)mod n)
(a-b)mod n=((a mod n)-(b mod n)+n)mod n
(a*b)mod n=(a mod n)(b mod n)mod n
5)大整数取模
问题
\quad 输入正整数n和m,输出n mod m的值。n<=10100,m<=109
分析
\quad 首先,把大整数写成“自左向右”的形式:1234=((1*10+2)*10+3)*10+4,然后用模运算公式,每步取模。
代码
int Big_Mod(char s[],int n,int m){
int ans=0;
for(int i=0;i<n;i++){
ans=(int)(((long long)ans*10+s[i]-'0')%m);
}
return ans;
}
6)幂取模
问题
\quad 输入正整数a、b和m,输出an mod m的值。a,n,m<=109
分析
\quad
在计算xn时,我们会怎么算呢?如果只是xxx*……*x这样每个数乘起来计算n次的话,虽然算法简单,但是复杂度为O(n),往往不能满足要求。
\quad
如果n=2k,可以将其表示为xn=((x2)2)…,只要做k次平方运算就可以了。
进一步思考,
- 当b为偶数时,ab可以转换成a2的b/2次方。
- 当b为奇数时,ab可以转化为a2的b/2次方,再乘以a。
像这样不断递归下去,每次n都减半,于是可以在O(log n)的时间内完成幂取模运算。
代码
int pow_mod(int a,int n,int m){
if(n==0) return 1;
int x=pow_mod(a,n/2,m);
long long ans=(long long)x*x%m;
if(n%2==1) ans=ans*a%m;
return (int)ans;
}
7)模线性方程组
问题
\quad 输入正整数a,b,n,解方程组ax=b(mod n)。a,b,n<=109
分析
a≡b(mod n)的充要条件是:a-b是n的整数倍。
\quad
这样,原来的方程就可以理解成:ax-b是n的正整数倍。设这个“倍数”为y,则ax-b=ny,所以ax-ny=b,可以使用扩展欧几里得算法来解决这个问题。
- 如果x是方程的解,则x≡y(mod n)的其他整数y也是方程的解。因此,当谈到同余方程的一个解时,其实指的是一个同于等价类。
- 当 b=1时,ax≡b(mod n)的解称为a关于模n的逆,根据上面的讨论我们可知,问题转换成ax-ny=1有解,即1必须是gcd(a,n)的倍数,因此,a和n必须互质(gcd(a,n)=1)。