扩展欧几里得算法。
void exgcd(int a,int b,int&x,int&y){ if(!b) { x=1;y=0;return ; } exgcd(b,a%b,x,y); int temp=x;x=y;y=temp-a/b*y; }
1)ax+by=c。
有解的条件是c%gcd(a,b)==0,因为ax+by=gcd(a,b)一定有解。
设解是x0,y0,则通解 x=x0+(b/gcd(a,b))*t y=y0-(a/gcd(a,b))*t
2)ax ≡1 (mod m)
x为a关于m的逆元,即ax-my=1,若gcd(a,m)!=1 无解
设解是x0,则通解 x=x0+m*t 则a关于m的逆元是关于m同余的。则最小正整数解∈(0,m),那么x=(x0%abs(m)+abs(m))%abs(m);
noip2012同余方程:求出ax ≡1(mod n) 的最小正整数解。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define clr(x,c) memset(x,c,sizeof(x)) void exgcd(int a,int b,int&x,int&y){ if(!b) { x=1;y=0;return ; } exgcd(b,a%b,x,y); int temp=x;x=y;y=temp-a/b*y; } int main(){ int a,b,x,y; scanf("%d%d",&a,&b); exgcd(a,b,x,y); x=(x%b+b)%b; printf("%d ",x); return 0; }
3)求ax≡t(mod b);
可以求出ax+by=gcd(a,b)的解,若t%gcd(a,b)!=0无解。否则最小整数解x=(x0%abs(b/gcd)+abs(b/gcd))%abs(b/gcd)*(c/gcd)
eg
int cal(int a,int b,int c){ int x,y; int gcd=exgcd(a,b,x,y); x*=c/gcd; b/=gcd; if(b<0) b=-b; return (x%b+b)%b; }