zoukankan      html  css  js  c++  java
  • 中国剩余定理

    中国剩余定理

    对于一组同余方程,(m_{1},m_{2}...m_{n}两两互质)

    [left{egin{array}{l} {x equiv a_{1}left(mod m_{1} ight)} \ {x equiv a_{2}left(mod m_{2} ight)} \ {cdots} \ {x equiv a_{n}left(mod m_{n} ight)} end{array} ight. ]

    有整数解。并且在模(M = m_{1}*m_{2}..m_{n})下的解是唯一的,解为

    [oldsymbol{x} equivleft(oldsymbol{a}_{1} M_{1} M_{1}^{-1}+a_{2} M_{2} M_{2}^{-1}+ldots+a_{k} M_{k} M_{k}^{-1} ight) mod M ]

    其中(M_{i} = frac{M}{m_{i}},M^{-1}_{i})(M_{i})(m_{i})的逆元

    #include <iostream>
    #include <cstdio>
    #define ll long long
    using namespace std;
    const int maxn = 1e5 + 5;
    void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){
        if(b == 0){
            d = a,x = 1,y = 0;
            return;
        }
        ex_gcd(b,a%b,d,y,x);
        y -= x*(a/b);
    }
    ll china(ll a[],ll m[],int n){//x = a (mod m)
        ll M = 1,y,d,x = 0;
        for(int i = 0; i < n; i++)M *= m[i];
        for(int i = 0; i < n; i++){
            ll w = M/m[i];
            ex_gcd(m[i],w,d,d,y);
            x = (x + a[i] * w * y) % M;
        }
        if((x + M) % M == 0) return M;
        return (x + M) % M;
    }
    int main(){
        int n;
        cin >> n;
        ll a[maxn],m[maxn];
        for(int i = 0; i < n; i++){
            cin >> a[i] >> m[i];
        }
        cout << china(a,m,n) << endl;
        return 0;
    }
    

    扩展中国剩余定理

    (m_{1},m_{2}...m_{n}不一定两两互质时)

    [left{egin{array}{l} {x equiv a_{1}left(mod m_{1} ight)} \ {x equiv a_{2}left(mod m_{2} ight)} \ {cdots} \ {x equiv a_{n}left(mod m_{n} ight)} end{array} ight. ]

    对于(egin{cases}x equiv a_1(mod m_1)\xequiv a_2(mod m_2) end{cases})

    进行变化有

    (egin{cases} x=a_1+k_1 imes m_1 \ x=a_2 +k_2 imes m_2 end{cases})

    (a_1 + m_1 imes k_1 = a_2 + m_2 imes k_2\m_1k_1 = (a_2 - a_1) + m_2k_2)

    方程有解当且仅当(gcd(m_1,m_2)|(a_2 - a_1))

    (gcd(m_1,m_2) = d)

    (frac{m_1k_1}{d} = frac{a_2 - a_1}{d} + frac{m_2k_2}{d} \ frac{m_1}{d}k_1 equiv frac{a_2 - a_1}{d}(mod frac{m_2}{d}))

    两边同时除(frac{m_1}{d})

    (k_1 equiv inv(frac{m_1}{d},frac{m_2}{d}) * frac{c_2 - c_1}{d} (mod frac{m_2}{d}) \ k_1 = inv(frac{m_1}{d},frac{m_2}{d}) * frac{a_2 - a_1}{d} + frac{m_2}{d} * y)

    把原式(x = a_1 + k_1m_1)带入

    (x = inv(frac{m_1}{d},frac{m_2}{d}) * frac{a_2 - a_1}{d} * m_1 + yfrac{m_1m_2}{d} + a_1 \ x equiv inv(frac{m_1}{d},frac{m_2}{d}) * frac{a_2 - a_1}{d} * m_1 + a_1(mod frac{m_1m_2}{d}))

    那么答案就是(x equiv a(mod m))

    其中(a = (inv (frac{m_1}{d}, frac{m_2}{d}) * frac{a_2 - a_1}{d}) \%frac{m_2}{d} *m_1 + a_1\m = frac{m_1m_2}{d})

    不断地进行两两合并,然后利用线性同余方程求出这两个同余方程的组的x,然后继续合并

    #include <iostream>
    #include <cstdio>
    #define ll long long
    using namespace std;
    const int maxn = 1e5 + 5;
    void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){
        if(b == 0){
            d = a,x = 1,y = 0;
            return;
        }
        ex_gcd(b,a%b,d,y,x);
        y -= x * (a/b);
    }
    ll mull(ll a,ll b,ll mod){
        ll ans = 0;
        while(b){
            if(b & 1)ans = (ans + a) % mod;
            a = (a + a) % mod;
            b >>= 1;
        }
        return ans;
    }
    ll ex_china(ll a[],ll m[],int n){//x = a(mod m)
        ll M = m[0];
        ll ans = a[0];
        ll d,x,y;
        for(int i = 1; i < n; i++){
            ex_gcd(M,m[i],d,x,y);
            if((ans - a[i]) % d)return -1;
            ll c = ((a[i] - ans) % m[i] + m[i]) % m[i];
            ll mod = m[i]/d;
            x = mull(x,c/d,mod);
            ans += x * M;
            M *= mod;
            ans = (ans % M + M) % M;
        }
        return ans;
    }
    int main(){
        int n;
        ll a[maxn],m[maxn];
        cin >> n;
        for(int i = 0; i < n; i++){
            cin >> a[i] >> m[i];
        }
        cout << ex_china(a,m,n) << endl;
        return 0;
    }
    
  • 相关阅读:
    ASP.NET MVC处理JsonResult返回时间DateTime问题
    ASP.NET MVC显示HTML字符串
    视图加载时自动执行铵钮事件
    呼叫外部js文件并使用其内部方法
    共用字段事件与结果不同关系与处理
    STOP:c0000218 {Registry File Failure}
    RDLC报表打印
    在Gridview如何进行每行单元格比较
    ASP.NET MVC在布局页上使用模型(model)
    Razor练习4
  • 原文地址:https://www.cnblogs.com/Emcikem/p/12234167.html
Copyright © 2011-2022 走看看