扩展欧几里得算法,可以在计算gcd(a,b)的同时,计算出
ax+by=gcd(a,b)中a、b的值
#include<stdio.h> #include<iostream> using namespace std;
long long ext_gcd(long long a, long long b, long long *x, long long *y)
{
if(b==0)
{
*x = 1,*y = 0;
return a;
}
else
{
long long r = ext_gcd(b, a%b, x, y);
long long t = *x;
*x = *y;
*y = t - a/b * *y;
return r;
}
}
int ext_gcd(int a, int b, int *x, int *y) { if(b==0) { *x = 1,*y = 0; return a; } else { int r = ext_gcd(b, a%b, x, y); int t = *x; *x = *y; *y = t - a/b * *y; return r; } }
int main() { int a,b; int x,y; while(1) { cin>>a>>b; cout<<"ext_gcd:"<<ext_gcd(a,b,&x,&y)<<endl; cout<<"ax+by=gcd(x,y)==>x y :"<<x<<" "<<y<<endl; cout<<"y*b:"<<y*b<<" y*b % a: "<<(y*b)%a<<" [(y*b%a)+a]%a: "<< ((y*b%a)+a)%a<<endl; } }
在求解出x,y之后,(x+b/gcd, y-a/gcd)都是可行的解。
通过ext_gcd,我们还可以求满足以下条件的方程的解:
a+cx%2^k=b,求解最小的x
a-b+cx%2^k=0
cx=(b-a)%2^k·························@1:典型的同余方程,通过ext_gcd求解
cx+(2^k)y=(b-a)
当且仅当 gcd(c,2^k)|(b-a)时,方程有解。
我们通过ext_gcd求得 cx+(2^k)y=gcd(b-a)的解 x,y,gcd.
把方程的两边同时/gcd*(b-a)即得到 @1式的解。
即 x = x*(b-a)/gcd。
因为我们要求最小的x,所以我们求出符合条件的x的变化周期:T:= (2^k)/gcd.
然后通过(x%T+T)%T得到最小的x,别问我为什么,因为我也不知道为什么。