五一之前再更一发,话说要为今年的邀请赛做准备了,但是我还什么都不会啊QAQ
今天主要更Euclid这个人发明的算法。欧几里得算法(Euclidean Algorithm),又称辗转相除法,是用来求解两个数的最大公约数的一种算法。其主要的思想是,设有正整数a,b,不妨令a>b,且a mod b≠0. gcd( a , b )=gcd( b , a mod b ),证明如下:
由于a mod b≠0,设a=k*b+r,即a mod b=r.设gcd( a , b )=c,则c|a且c|b.
令a=m*c,b=n*c且mn互质,r=a-k*b=m*c-n*c*k=(m-n*k)c,也即c|r. 由于n与m-n*k互质,(证:若n与m-n*k不互质,设gcd(n,m-n*k)=d,且d>1.令n=xd,m-n*k=yd,且xy互质,则y+xk与x互质。gcd(a,b)=gcd(xcd,(y+xk)cd)=cd>c,与假设矛盾)所以gcd( b , r )=c=gcd( a , b ).证毕。代码的话很好写,一行递归就搞定了,在这儿就不放上来了。
然后要说的是扩展欧几里得算法(extended Euclidean algorithm)。exgcd的主要思想为:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。下证:
#include
using namespace std;
long long exgcd(long long a,long long b,long long& x,long long& y)
{
if(!b)
{
x=1;
y=0;
return a;
}
long long r=exgcd(b,a%b,y,x);
y-=a/b*x;
return r;
}
int main(){
long long a,b,c,d;
while(cin>>a>>b>>c>>d){
cout<
辣么exgcd有什么用呢?至少有以下3个作用:
1、求解不定方程;
2、求解模线性方程(线性同余方程);
3、求解模的逆元。
关于求解不定方程,可以参考这一篇博客http://www.cnblogs.com/void/archive/2011/04/18/2020357.html
关于求解同余方程和乘法逆元,实际上都是把他们转化成ax+ ny= b的方程形式求解。
同余方程 ax≡b (mod n)对于未知数 x 有解,当且仅当 gcd(a,n) | b。且方程有解时,方程有 gcd(a,n) 个解。
设 d= gcd(a,n),假如整数 x 和 y,满足 d= ax+ ny(用扩展欧几里德得出)。如果 d| b,则方程
a* x0+ n* y0= d, 方程两边乘以 b/ d,(因为 d|b,所以能够整除),得到 a* x0* b/ d+ n* y0* b/ d= b。
所以 x= x0* b/ d,y= y0* b/ d 为 ax+ ny= b 的一个解,所以 x= x0* b/ d 为 ax= b (mod n ) 的解。
ax≡b (mod n)的一个解为 x0= x* (b/ d ) 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;
相关证明:
证明方程有一解是: x0 = x'(b/d) mod n;
由 a*x0 = a*x'(b/d) (mod n)
a*x0 = d (b/d) (mod n) (由于 ax' = d (mod n))
= b (mod n)
证明方程有d个解: xi = x0 + i*(n/d) (mod n);
由 a*xi (mod n) = a * (x0 + i*(n/d)) (mod n)
= (a*x0+a*i*(n/d)) (mod n)
= a * x0 (mod n) (由于 d | a)
= b
证毕。
你可能感兴趣的:(算法)