一个不用中国剩余定理求解线性同余方程组的方法。

  现在我们有x = b1(mod m1), x = b2(mod m2) ... x = bn(mod mn) 求解一个最小的使其满足上述方程,我们首先考虑x = b1 (mod m1), x = b2 (mod m2)这两个方程, 如果我们用这两个方程求出了一个解x0, 那么其一个解为x = x0 mod([m1, m2]), 通过这个办法我们将两个方程合成一个方程。 对于n个方程我们进行n-1次操作即可就出方程组的解。 现在思考如何将两个方程合并成为一个方程, x = b1(mod m1) => x  = b1 + m1*y x = b2(mod m2) => x = b2 + m2*z 合并两式得到m1*y-m2*z=b2-b1,现在就可以用egcd求出一个解, 然后就可以顺利求出x了。代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;
typedef long long LL;

LL gcd(LL a, LL b)
{
    if(!b) return a;
    else return gcd(b, a%b);
}
LL lcm(LL a, LL b)
{
    return a/gcd(a, b)*b;
}
void egcd(LL a, LL b, LL &d, LL &x, LL &y)
{
    if(!b) { d=a; x=1; y=0; }
    else { egcd(b, a%b, d, y, x); y -= x*(a/b); }
}

LL solve(LL bb[], LL m[], int len)    //返回最小解
{
    for(int i=1; i<len; i++)
    {
        LL g, x, y;
        LL a=m[0], b=-m[i], c=bb[i]-bb[0];
        egcd(a, b, g, x, y);
        if(c%g != 0) return -1;          //此时无解
        x = c/g*x;
        x = m[0]*x + bb[0];
        m[0]=lcm(m[0], m[i]);
        bb[0]=(x%m[0]+m[0])%m[0];
    }
    return bb[0];
}

int main()
{
    int len;
    LL bb[100], m[100];
    cin>>len;
    for(int i=0; i<len; i++)
    {
        cin>>bb[i]>>m[i];
    }
    cout<<solve(bb, m, len)<<endl;
    return 0;
}

 

posted @ 2016-02-20 14:22  xing-xing  阅读(1025)  评论(0编辑  收藏  举报