中国剩余定理的详细探讨

/*
    中国剩余定理
    有这么一系列同余方程组
    X ≡ b1 (mod m1)
    X ≡ b2 (mod m2)
    X ≡ b3 (mod m3)
    ···
    X ≡ bn (mod mn)
    也就是 X 除 m1 余 b1 ,X 除 m2 余 b2...以此类推
    我们来分两大类讨论 X 的解
 
    1.m1,m2,m3,...,mn两两互质
    设 M = m1*m2*m3*...*mn,
    即 mi(i = 1,2,...) 的最小公倍数,由于两两互质,所以可以这么求
    此时 M ≡ 0 (mod mi) (i = 1,2,...)
    再设 Mi = M/mi
    此时 gcd(Mi,mi) = 1            ⓵
    因为我们从 M 的因子中拿去了 mi,导致 M 与 mi 互质
    也就是说,我们从⓵可以得到同余方程
    Mi * xi ≡ 1 (mod mi)          ⓶
    此时两边同时乘以 bi,得
    bi * Mi * xi ≡ bi (mod mi)    ⓷
 
    再设置 Mj,此时
    mk | Mj (这是因为 Mj 中仅缺少了 mj 这一个因子,并没有缺少 mk)
    所以
    mk | Mj * bj * xj             ⓸
    所以得到 X 的通解,即
    S = ( M1 * b1 * x1 ) + ( M2 * b2 * x2 ) +...+ ( Mr * br * xr )
    这是因为对某一个数取模时,只对其中一个项有着作用,拿 “X ≡ b1 (mod m1)” 来说
    当对 X 的通解取模时,其余项都是m1的倍数,在取模过程中可以直接被约去,也就是:
    S - ( M1 * b1 * x1) = ( M2 * b2 * x2 ) +...+ ( Mr * br * xr )
    S - ( M1 * b1 * x1) ≡ 0 (mod m1)
    S - ( M1 * b1 * x1) - ( M2 * b2 * x2 ) ≡ 0 (mod m1 * m2)    ⓹
    所以我们可以得到以下同余方程组:
    S ≡ M1 * b1 * x1 (mod m1)
    S ≡ M2 * b2 * x2 (mod m2)
    S ≡ M3 * b3 * x3 (mod m3)
    ...
    S ≡ Mr * br * xr (mod mr)
    正好与刚开头的同余方程组相对应,则我们可以得到总的一个公式:
    X ≡ S (mod M)
    X ≡ ( M1 * b1 * x1 ) + ( M2 * b2 * x2 ) +...+ ( Mr * br * xr ) (mod M)
    Mi = M/mi, xi 为 Mi * x ≡ 1 (mod mi)的解
 
 
    2.m1,m2,m3,...mr非互质的的情况以及同余方程的合并和无解的情况
 
    第一种情况——bi一致
    我们需要知道以下定理:
    如果 a ≡ b (mod n) , a ≡ b (mod m) , 那么 a ≡ b ( mod m*n/gcd(m,n) )
    如果 gcd(m,n) = 1 , 也就是互质,那么 a ≡ b (mod m*n)
    所以运用这个定理可以使得下面两个同余方程合并
    a ≡ b (mod n)
    a ≡ b (mod m)
 
    第二种情况——bi不一致的非互质中国剩余定理
    a ≡ b1 (mod m)
    a ≡ b2 (mod m^i)
    我们知道:
    m | m^i , m^i | a-b2 , m | a-b1
    所以,我们可以得出
    m | (a-b2)-(a-b1) = m | (b1-b2)
    也就是说,如果不满足 m | (b1-b2),那么方程无法合并,也就是无解
    如果 m | (b1-b2)满足,那么设 b1-b2 = cm,则b1 = b2+cm
    则
    a ≡ b2+cm (mod m^i)
    a ≡ b2 (mod m^i)
    合并得到
    a ≡ b2 (mod m^i)
 
    第三种情况——最为一般的情况
    X ≡ b1 (mod m)      ⓵
    X ≡ b2 (mod n)      ⓶
    d = gcd(m,n) ≠ 1    ⓷
    从⓷我们可以初步得到:
    d | m ,d | n
    也就是
    m = c1 * d , n = c2 * d
    从⓵⓶可以知道
    m | X - b1
    n | X - b2
    即
    c1d | X - b1
    c2d | X - b2
    移项得到:
    c1d+b1 | X
    c2d+b2 | X
    则:
    c1d+b1 = c2d+b2
    (c1-c2)d = b2-b1
    即
    d | b2-b1
    若不满足 d | b2-b1 ,则无解
    若满足,把同余方程化成以下形式:
    X ≡ b1 + c1m (mod m)
    X ≡ b2 + c2n (mod n)
    使 b1 + c1m = b2 + c2n
    然后再带入到第一种形式合并方程
 */
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
ll x,y;
ll gcd(ll a,ll b)
{
    if(b == 0)
        return a;
    else return gcd(b,a%b);
}
ll exgcd(ll a,ll b)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    ll r = exgcd(b, a%b);
    ll t = x;x = y;y = t - a/b * y;
    return r;
}
ll inv(ll a,ll b)//求a关于模b的逆元,如果gcd(a,b)!=1,则无解
{
    ll d = exgcd(a, b);
    if(d != 1) return 0;
    else
        return (x+b)%b;
}
bool merge(ll b1,ll m1,ll b2,ll m2,ll &b3,ll &m3)//方程的合并
{
    ll d = gcd(m1, m2);
    if((b2-b1)%d != 0) return false;
    ll c = b2-b1;
    c = (c+m2)%m2;
    c /= d;
    m1 /= d;//使m1,m2互质
    m2 /= d;
    /*
     上面是消元的过程,比如
     X ≡ -1 (mod 6)
     X ≡ 1 (mod 4)
     gcd(6,4) = 2
     ∵ 2 | 1+1
     ∴ -1 + c1*6 = 1 + c2*4
     c1*6 = 2 + c2*4    //对应136行
     6 | 2 + c2 * 4
     ∴4c2 ≡ -2 (mod 6)
      2c2 ≡ -1 (mod 3)  //对应138-140行
      2c2 ≡ 2 (mod 3)
       c2 ≡ 1 (mod 3)
     ∴ c2 = 1
     */
    c *= inv(m1,m2);
    c %= m2;
    c *= m1*d;  //仔细对照 -1 + c1*6 = 1 + c2*4
    c += b1;
    m3 = m1*m2*d;
    b3 = (c+m3)%m3;
    return true;
}
ll China_ReMinder(ll len,ll b[],ll m[])
{
    ll b1 = b[0],m1 = m[0];
    ll b2,m2;
    for(ll i=1;i<len;i++)//n-1次合并
    {
        ll bb,mm;
        b2 = b[i];m2 = m[i];
        if(!merge(b1,m1,b2,m2,bb,mm)) return -1;
        b1 = bb;
        m1 = mm;
    }
    return (b1+m1)%m1;
    //最小解S = [( M1 * b1 * x1 ) + ( M2 * b2 * x2 ) +...+ ( Mr * br * xr )]%M
}
ll b[10010],m[10010];
int main()
{
    ll k;
    cin>>k;
    for(int i=0;i<k;i++)
    {
        cin>>m[i]>>b[i];
        if(m[i] == 0)
        {
            cout<<"-1"<<endl;
            return 0;
        }
    }
    cout<<China_ReMinder(k, b, m)<<endl;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值