数学板块学习之中国剩余定理及扩展中国剩余定理

更新ing

中国剩余定理

用于求解一元线性同余方程组
{ x % m 1 = a 1 x % m 2 = a 2 x % m 3 = a 3 ⋮ x % m k = a k \begin{cases} x\%m_{1}=a_{1}\\ x\%m_{2}=a_{2}\\ x\%m_{3}=a_{3}\\ \vdots\\ x\%m_{k}=a_{k} \end{cases} x%m1=a1x%m2=a2x%m3=a3x%mk=ak

其中 m i m_i mi两两互质

--------------------------------我是来自百度百科的分界线-----------------------------------

孙子定理是中国古代求解一次同余式组(见同余)的方法。是数论中一个重要定理。又称中国余数定理。一元线性同余方程组问题最早可见于中国南北朝时期(公元5世纪)的数学著作《孙子算经》卷下第二十六题,叫做“物不知数”问题,原文如下:
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。《孙子算经》中首次提到了同余方程组问题,以及以上具体问题的解法,因此在中文数学文献中也会将中国剩余定理称为孙子定理。

中国剩余定理说明:假设整数 m 1 , m 2 , ⋯   , m n m_{1},m_{2}, \cdots ,m_{n} m1,m2,,mn两两互质,则对任意的整数: a 1 , a 2 , ⋯   , a n a_{1},a_{2},\cdots ,a_{n} a1,a2,,an,方程组有解,并且通解可以用如下方式构造得到:
M M M是整数 m 1 , m 2 , ⋯   , m n m_{1},m_{2}, \cdots ,m_{n} m1,m2,,mn的乘积,并设 M i = M m i , i ∈ ( 1 , 2 , 3 , ⋯   , n ) M_{i}=\frac{M}{m_{i}},i\in{(1,2,3,\cdots,n)} Mi=miM,i(1,2,3,,n)是除了 m i m_{i} mi以外的n- 1个整数的乘积。
t i = M i − 1 t_{i}=M_{i}^{-1} ti=Mi1 M i M_{i} Mi m i m_{i} mi的数论倒数( t i t_{i} ti M i M_{i} Mi m i m_{i} mi意义下的逆元)
方程组的通解形式为 x = a 1 t 1 M 1 + a 2 t 2 M 2 + ⋯ + a n t n M n = Σ i − 1 n a i t i M i x=a_{1}t_{1}M_{1}+a_{2}t_{2}M_{2}+\cdots+a_{n}t_{n}M_{n}=\Sigma_{i-1}^{n}a_{i}t_iM_i x=a1t1M1+a2t2M2++antnMn=Σi1naitiMi
在模 M M M的意义下,方程组只有一个解: x = ⟮ Σ i − 1 n a i t i M i ⟯ % M x=\lgroup \Sigma_{i-1}^{n}a_{i}t_iM_i \rgroup \%M x=Σi1naitiMi%M


代码

int k;
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){
    if(!b){
        d = a;x = 1;y = 0;return;
    }
    ex_gcd(b,a%b,d,y,x);
    y -= x*(a/b);
}

ll inv(ll a,ll p){
    ll d,x,y;
    ex_gcd(a,p,d,x,y);
    return d == 1 ? (x%p+p)%p : -1;
}

ll crt(int n,ll *a,ll *m){ // x%m[i]=a[i]
    ll M = 1,ret = 0;
    for(int i = 1; i <= n; ++i) M *= m[i];
    for(int i = 1; i <= n; ++i){
        ll Mi = M / m[i];
        ret = (ret + Mi*inv(Mi,m[i])*a[i])%M;
    }
    return (ret+M)%M;
}

ll m[maxn],a[maxn];
int main(){
    int n;
    cin>>n;
    for(int i = 1; i <= n; ++i){
        scanf("%lld%lld",&m[i],&a[i]);
    }
    ll ans = crt(n,a,m);
    printf("%lld\n",ans);
    return 0;
}

拓展中国剩余定理

将中国剩余定理拓展到 m i m_{i} mi不互质的情况
代码

void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){
    if(!b){
        d = a;x = 1;y = 0;return;
    }
    ex_gcd(b,a%b,d,y,x);
    y -= x*(a/b);
}


ll ex_crt(int n,ll *a,ll *m){ // x%m[i]=a[i]
    ll d,M = m[1],A = a[1],x,y;
    for(int i = 2; i <= n; ++i){
        ex_gcd(M,m[i],d,x,y);
        ll c = a[i]-A;
        if(c%d) return -1;
        ll mul = m[i]/d;
        x = (c/d*x%mul+mul)%mul;
        A = A+M*x;
        M = M*mul;
        A %= M; 
    }
    return (A+M)%M;
}

ll m[maxn],a[maxn];
int main(){
    int n;
    cin>>n;
    for(int i = 1; i <= n; ++i){
        scanf("%lld%lld",&m[i],&a[i]);
    }
    ll ans = ex_crt(n,a,m);
    printf("%lld\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值