扩展欧几里德解二元一次不定方程

扩展欧几里得算法详见:@zhj5chengfeng
http://blog.csdn.net/zhjchengfeng5/article/details/7786595

对于二元一次不定方程: ax + by = c;

有解的充要条件是 : c % gcd(a,b) ==0;
可用扩展欧几里得算法求得 某一个解 x, 但不一定是最终解;
最终解应为X = x * c /gcd(a,b);
当然,此时 X 不一定是正数,可通过
X = ( X %(b/gcd(a,b)) + (b/gcd(a,b))) % (b/gcd(a,b));
来调整

应用例题:poj2115:
此题 容易推出 方程: (A + Cx)% 2^k = B;
即 Cx = (B-A) (mod 2^k) //(同余方程…)

再整理成 不定方程的形式就是: Cx + (2^k)y = (B-A)
然后 对应上面的解法 代入就 可以了。。。

代码

///poj2115
//Time; 16MS
//Memory: 724K
///编译器打三杠才清楚。。。请谅解

#include
#include
#include
#include
using namespace std;
typedef long long int LL;


LL ex_gcd(LL a, LL b, LL &x,LL &y)
{
    if(b==0)
    {
        x = 1;
        y = 0;
        return a;
    }

    LL ans = ex_gcd(b,a%b,x,y);
    LL temp = x;
    x = y;
    y = temp - a/b*y;

    return ans;
}




int main()
{
    LL A,B,C,k;
    while(cin>>A>>B>>C>>k)
    {
       if(!A&&!B&&!C&&!k) break;

       if(A==B) {cout<<"0"<continue;}

       LL M = (LL)1<//cout<

       LL G = B-A;

       ///方程: C*x + M*y = G ;


       LL x,y;
       LL ans = ex_gcd(C,M,x,y);
///ans == gcd(C,M);
       //cout<
       //cout<
       if(G%ans != 0) {cout<<"FOREVER"<continue;}
///有解条件 G % gcd(C,M) == 0;


     //  cout<

       LL k = M/ans;  //

       LL ret =  x*G/ans;  ///最终解

       ret = (ret%(k) + (k))%k;  ///(调整)最终解,使之为可行的最小正整数

       cout<return 0;
}

你可能感兴趣的:(ACM,数论)