扩展欧几里得算法:
ax+by=gcd(a,b)ax+by=gcd(a,b)ax+by=gcd(a,b) 求出满足条件唯一的x,y的值
设:设:设:
r0=q1∗r1+r2r_{0}=q_{1}*r_{1}+r_{2}r0=q1∗r1+r2
r1=q2∗r2+r3r_{1}=q_{2}*r_{2}+r_{3}r1=q2∗r2+r3
r2=q3∗r3+r4r_{2}=q_{3}*r_{3}+r_{4}r2=q3∗r3+r4
..............................
rk−1=qk∗rkr_{k-1}=q_{k}*r_{k}rk−1=qk∗rk
其中rkr_{k}rk 就是最大公约数,因为rkr_{k}rk可由rk−1r_{k-1}rk−1和rk−2r_{k-2}rk−2,且rn=rn−2−qn−1∗rn−1r_{n}=r_{n-2}-q_{n-1}*r_{n-1}rn=rn−2−qn−1∗rn−1
故rk−1r_{k-1}rk−1可表示为rk−2r_{k-2}rk−2和rk−3r_{k-3}rk−3的线性组合
同理rk−2r_{k-2}rk−2也可向上表示。这样得到最大公约数之后,一直向上回溯即可找到满足条件的x,y
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll ExGcd(ll a,ll b,ll &x,ll &y)//求 a b 最大公约数,且得到gcd(a,b)=x*a+y*b;
{
if(!b)
{
x=1;
y=0;
return a;
}
ll gcd=ExGcd(b,a%b,x,y);
ll temp,k;
k=a/b;
temp=x;
x=y;
y=temp-k*y;
return gcd;
}
利用扩展欧几里得求一次同余方程
形如式子a∗x=c (mod m)a*x=c\ \ \ (mod \ \ m)a∗x=c (mod m),求满足条件的x。
- 且只有满足gcd(a,m)∣cgcd(a,m)|cgcd(a,m)∣c 的时候才有解。
ax1+my1=gcd(a,m) ①ax_{1}+my_{1}=gcd(a,m)\ \ \ \ \ \ \ ①ax1+my1=gcd(a,m) ①
令c1=c/gcd(a,m)c_{1}=c/gcd(a,m)c1=c/gcd(a,m),
那么等式①两边同乘以c1c_{1}c1即可得到ax1c1+my1∗c1=cax_{1}c_{1}+my_{1}*{c1}=cax1c1+my1∗c1=c
即x=x1∗c1=x1∗c/gcd(a,m)x=x_{1}*c_{1}=x_{1}*c/gcd(a,m)x=x1∗c1=x1∗c/gcd(a,m)(x1x_{1}x1为(a,m)(a,m)(a,m)的扩展欧几里得公式中a的系数)
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll ExGcd(ll a,ll b,ll &x,ll &y)//求 a b 最大公约数,且得到gcd(a,b)=x*a+y*b;
{
if(!b)
{
x=1;
y=0;
return a;
}
ll gcd=ExGcd(b,a%b,x,y);
ll temp,k=a/b;
temp=x;
x=y;
y=temp-k*y;
return gcd;
}
bool IsOk;
ll calc(ll a,ll c,ll m)
{
ll x,y;
ll gcd=ExGcd(a,m,x,y);
if(c%gcd!=0)
{
IsOk=false;
return 0ll;
}
return c/gcd*x%m;
}
利用费马小定理求逆元
补充一个 欧拉定理:
设φ(x)的x的欧拉函数值,如果有a和p互素,则有
aφ(p)=1(mod p)a^{φ(p)}=1(mod \ p)aφ(p)=1(mod p)
- 费马小定理条件:a,p互素,且p是素数
则:ap−1=1 (mod q)a^{p-1}=1\ (mod \ q)ap−1=1 (mod q)
即:aaa 关于ppp 的逆元为 ap−2a^{p-2}ap−2
/*
快速幂取模即可
*/
利用扩展欧几里得求逆元
前提
gcd(a,q)==1
逆元即ax+qy=1 (mod q)中的x
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=1e4+10;
ll ExGcd(ll a,ll b,ll &x,ll &y)//求 a b 最大公约数,且得到gcd(a,b)=x*a+y*b;
{
if(!b)
{
x=1;
y=0;
return a;
}
ll gcd=ExGcd(b,a%b,x,y);
ll temp,k;
k=a/b;
temp=x;
x=y;
y=temp-k*y;
return gcd;
}
ll getinv(ll a,ll m)
{
ll x,y;
if(ExGcd(a,m,x,y)!=1)
return -1;//不互质 不存在逆元
return x;
}