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


      现在我们有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;
    }
  • 相关阅读:
    Boost Started on Windows
    7-Zip
    代码的命名规则
    基础扫盲:YEAR关键字 IN操作符
    基础扫盲:INSERT INTO 和 SELECT 结合使用
    知识盲点:存在外键的的表,在插入数据时应该如何操作?
    SQL Identity函数
    SQL 中DateName()函数及DatePart()函数
    OS开发多线程篇—GCD介绍
    经典SQL语句大全
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5203210.html
Copyright © 2020-2023  润新知