相关概念引入:
逆元:假如ax≡1(mod m)则称a关于1模m的逆元为x。当然了x有解的前提是gcd(a,m)=1。
小费马定理:p为质数,ap≡a(mod p),若gcd(a,p)=1,则
a(p-1)≡1(mod p)------- a*a(p-2)≡1(mod p)所以a(p-2)为a的逆元;结合快速幂求a(p-2)
long long quick_pow(int a,int b)
{
long long sum=1;
while(b>0)
{
if(b&1)
sum*=a;
a*=a;
b>>=1;
}
}
介绍了小费马定理顺便学习一下欧拉定理
欧拉定理: 若gcd(a,m)=1,则aφ(m)=1(mod m) ;φ(m)为所有比m小且与m互质的数的个数(互质:两个数的gcd等于1)
与小费马定理对比一下。(如果m为质数那么,φ(m)=m-1,任意比m小的数都与m互质)
欧几里得定理:辗转相除法,用于求两个数的最大公约数。
具体做法就是:
int gcd(int a,int b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
不断的用上一次的除数去除以上一次的余数。
拓展欧几里得: 逆元是ax≡1(mod m)即ax=1+km;
解一元二次方程组ax+by=gcd(a,b);观察欧几里得算法可以知道当a=gcd,b=0时终止。如果应用在上面的方程组中则当a=gcd时x=1,b=0时y的值不用管。是否能够由终极形态向上推出最初的x和y的解呢,当然可以.由欧几里得算法我们可以知道gcd(a,b)=gcd(b,a%b).假如我们下一个状态:b * x1+a%b * y1=gcd(a,b)一组解x1,y1。而a%b=a-a/b*b。
所以
b * x1 + (a - a / b * b) * y1=gcd(a,b)
b * (x1 - a/b * y1) + a * y1=gcd(a,b)
对比求解的方程组ax+by=gcd(a,b);
x=y;
y=x-a/b*y;
void exgcd(int a,int b)
{
if(b==0)
{
x=1;
y=0;
}
else
{
exgcd(b,a%b);
int tmp=x;
x=y;
y=tmp-a/b*y;
}
}
void finv(int a,int b)
{
exgcd(a,b);
x=(x%b+b)%b;//防止x<0
}