1、欧几里得原理
(1)欧几里得算法
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
(2)、拓展欧几里得:在已知a、b的情况下,求x*a+b*y=gcd(a,b)的一组整数解
1)、推导:
/* 设 a* x1+b* y1=gcd(a, b), b* x2+(a%b)*y2=gcd(b, a%b);
因为 gcd(a, b)==gcd(b, a%b)
所以 a*x1+b*y1=b*x2+(a%b)*y2
设 r=a%b, r =a-k* b
则 a* x1+b* y1=b* x2+(a-k* b)*y2
a* x1+b* y1=b* x2+(a-(a/b)* b)*y2
a* x1+b* y1=b* x2+a*y2-b*(a/b)*y2
a* x1+b* y1=a* y2+b* (x2+(a/b)y2) /
即 x1=y2,y1=x2+a/b*y2
2)、代码:
long long ex_gcd(long long a,long long b,long long &x,long long &y)
{
if(b==0)
{
x=1,y=0;
return a;
}
long long r,y1,x1;
r=gcd(b,a%b,x1,y1);
x=y1,y=x1-a/b*y1;
return r;
}
//当不用判断a,b是否互质时可写为:
void ex_gcd(lnog long a,long long b,long long &x,long long &y)
{
if(b==0)
{
x=1;y=0;
return;
}
long long x1,y1;
ex_gcd(b,a%b,x1,y1);
x=y1;y=x1-a/b*y1;
}
(3)、应用
1)、判断a* x+b*y=c有无整数解:
设 d=gcd(a,b);
if(c%d!=0)无解 else 有解
2)、求a* x+b*y=c通解
设a* x+b*y=d=gcd(a,b)的解为x0、y0
则a* x+b*y=c的解为 x=x0*c/d y=y0*c/d
通解为 x=x0*c/d+k*b/d y=y0*c/d-k*a/d (k为整数)
3)、解模线性方程
//模线性方程:形如 “ax≡1(mod n)” 的方程
设(ax-b)=ny ,则ax-ny=b….
eg: NKOJ 1886 http://blog.csdn.net/Y__XV/article/details/51458654
4)、求乘法逆元
详见后
2、费马小定理:若p为质数,且a、p互质,则a^(p-1)≡1(mod p)
应用:求乘法逆元
详见后
3、乘法逆元:ax≡1(mod n)的最小正整数解称为a关于模n的乘法逆元。
(1)、存在条件:an-ny=1有解
(2)、求法
1)、拓欧求
long long inverse(long long a)
{
long long x,y;
if(gcd(a,n,x,y)==1) return (x+n)%n;
return -1;
}
2)、费马小定理求
设x关于模n的乘法逆元为x0,则(x*x0)≡1(mod n)
又因为x^(t-1)≡1(mod n)
x0=x^(t-2)
(3)、应用:
1)、逆元(a/b)%p==(a*b0)%p
2)、降幂(a^b%p=a^(b%(p-1))%p)