中国剩余定理

Chinese Remainder Theorem(CRT),中文名又称孙子定理,是唯一以“Chinese”为关键词命名的数学定理,这是我们中华民族的骄傲!

线性同余方程组

CRT 主要解决线性同余方程组的问题,在数学著作《孙子算经》卷下,有一个叫做“物不知数”问题,原文如下:

有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?

意思就是一个整数除以三余二,除以五余三,除以七余二,求这个整数。

这蕴涵着一个线性同余方程组:

\[\begin{cases} x\equiv 2\ (\bmod\ 3)\\ x\equiv 3\ (\bmod\ 5)\\ x\equiv 2\ (\bmod\ 7)\\ \end{cases}\]

其中 \(x\in\mathbb N^*\)

我们可以拓广到一般的线性方程组,形式如下:

\[\begin{cases} x\equiv r_1\ (\bmod\ v_1)\\ x\equiv r_2\ (\bmod\ v_2)\\ \dots\ \dots\\ x\equiv r_m\ (\bmod\ v_m)\\ \end{cases}\]

其中 \(x\in\mathbb N^*\)

解法

显然,这个线性同余方程组不具有唯一解,先考虑 \(r_1,r_2\dots,r_m\) 互素的情况,这也是一般的中国剩余定理。

众所周知,模运算具有不少良好的性质,我们用到如下几个:

  1. \(x\equiv a\ (\bmod\ c)\),且 \(y\equiv b\ (\bmod\ c)\),则 \(x+y\equiv a+b\ (\bmod\ c)\),若 \(b=0\) 为特殊情况;
  2. \(x\equiv a\ (\bmod\ c)\),且 \(y\equiv b\ (\bmod\ c)\),则 \(xy\equiv ab\ (\bmod\ c)\),当 \(a=0\)\(b=0\) 时,可得 \(xy\equiv 0\ (\bmod\ c)\)

那么,考虑先找到线性方程组的特解 \(x'\),然后对于 \(x'\) 进行加加减减得到最终的通解,那么,我们可以让 \(x'=A_1+A_2+\dots+A_m\),其中 \(A_i\) 满足如下性质:

  1. \(\forall j\neq i\)\(j\in[1,m]\)\(v_j|A_i\)
  2. \(A_i\equiv r_i\ (\bmod\ v_i)\)

显然,这很容易构造,我们令 \(F_i=\frac{\prod^m_{i=1}v_i}{v_i}\)

然后易构造 \(x'=\sum_{i=1}^m{F_i}{(F_i\bmod v_i)^{-1}r_i}\) 即可,其中 \((F_i\bmod v_i)^{-1}\) 为模 \(v_i\) 意义下 \(F_i\) 的逆元。

详细的解释一下:

对于第 \(i\) 个线性同余方程 \(x\equiv r_i\ (\bmod\ v_i)\),我们考虑 \(x'\) 的每一项对于 \(v_i\) 的余数:

对于 \(j\neq i\)\({F_i}{(F_i\bmod v_i)^{-1}r_i}\bmod v_i=0\),因为根据我们的构造,\(v_i|F_j\),所以 \(v_i|{F_i}{(F_i\bmod v_i)^{-1}r_i}\)
对于 \(i\)\({F_j}{r_j}\equiv r_i\ (\bmod\ v_i)\),因为显然,根据逆元的定义,\({F_i}(F_i\bmod v_i)^{-1}\equiv 1\ (\bmod\ v_i)\),那么这样,\({F_i}{(F_i\bmod v_i)^{-1}r_i}\equiv r_i\times 1\ (\bmod\ v_i)\),显然,与 \(r_i\) 同余。

那么,\(\sum_{i=1}^m{F_i}{(F_i\bmod v_i)^{-1}r_i}\equiv 0+0+\dots+r_i+\dots+0\ (\bmod\ v_i)\),其中,第 \(i\) 项为 \(r_i\)

代码

#include<bits/stdc++.h>
#define ll long long
#define i128 __int128 
using namespace std;
const int N = 1e5+7;
ll v[N],r[N];
int phi[N];
ll qpow(ll a,ll b,ll mod) {
    if(b==0) return 1;
    if(b==1) return a;
    ll res=qpow(a,b/2,mod);
    res=res*res%mod;
    if(b&1) res=res*a%mod;
    return res;
}
void init() {
    for(int i=1;i<N;++i) phi[i]=i;
    for(int i=2;i<N;++i) {
        if(phi[i]!=i) continue;
        for(int j=i;j<N;j+=i)
            phi[j]=phi[j]*(i-1)/i;
    }
}
inline i128 inv(i128 a,i128 mod) {
    return qpow(a%mod,phi[mod]-1,mod);
}
signed main() {
    int n;
    i128 prod=1,res=0;
    init();
    cin>>n;
    for(int i=1;i<=n;++i) cin>>v[i]>>r[i],prod*=v[i];
    for(int i=1;i<=n;++i) {
        r[i]%=v[i];
        i128 cur=prod/v[i];
        i128 iv=inv(cur,v[i]);
        res+=iv*r[i]*cur;
        res%=prod;
    } cout<<(ll)(res)<<'\n';
    return 0;
}
posted @ 2024-01-04 12:30  abensyl  阅读(57)  评论(0)    收藏  举报
//雪花飘落效果