扩展欧几里得所能求的东西:不定方程的某一整数解,同余方程,乘法逆元
首先了解一个性质(裴蜀定理):ax+by=c 有整数解当且仅当c为gcd(a,b)的倍数
然后是两个预备知识:gcd(a,b)=gcd(b,a%b) a%b=a-a/b*b(此处/表示整除)
不定方程的解:
不妨设a>b
另ax1+by1=gcd(a,b) bx2+(a%b)y2=gcd(b,a%b)
因为gcd(a,b)=gcd(b,a%b)
所以 ax1+by1=bx2+(a%b)y2
因为a%b=a-a/b*b
所以ax1+by1=ay2+b(x2-(a/b)*y2)
所以x1=y2 ; y1=x2-(a/b)*y2
这样就可以递归处理 显然当b=0时为边界条件
我们令当b=0时 x=1 y=0
然后慢慢回溯
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #define int long long using namespace std; int exgcd(int a,int b,int &x,int &y) { int d,t; if(b==0) { x=1;y=0; return a; } d=exgcd(b,a%b,x,y); t=x-a/b*y; x=y; y=t; return d; } signed main() { int a,b,x,y,d; scanf("%lld %lld",&a,&b); d=exgcd(a,b,x,y); printf("%lld",(x%(b/d)+(b/d))%(b/d)); }
求出不定方程的最小解
emmm其实就是上面的输出。
因为x%(b/d)可能为负数 所以要加上b/d 然后再模b/d
同余方程
axΞp(mod b)
方程可改写为ax=by+p →ax+by=p(注意此处移项后y的系数并没有取相反数,因为y的值对这个式子没有影响)
显然当p为gcd(a,b)的倍数的时候,有整数解
然后就是emmmm不定方程的解法了
乘法逆元
首先科普一下逆元是什么意思(令a在mob p的情况下逆元的符号为inva)
a*invaΞ1(mod p) 对,这个就是乘法逆元的作用
那么如何用扩展欧几里得求乘法逆元呢
令x=inva b=p
然后就完事了
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; void exgcd(int a,int b,int &x,int &y) { int t; if(b==0) { x=1;y=0; return ; } exgcd(b,a%b,x,y); t=x-a/b*y; x=y; y=t; return ; } inline int niyuan(int a,int m) { int x,y; exgcd(a,m,x,y); return (x%m+m)%m; } int main() { int n,p; scanf("%d %d",&n,&p); for(register int i=1;i<=n;i++) { printf("%d\n",niyuan(i,p)); } }
总结:不管是同余方程还是乘法逆元,都是将其转换为不定方程的形式,再进行扩展欧几里得的运算