考虑一个同余方程组
\[
\begin{cases}x \equiv a_1 \ (mod \ b_1) \\x \equiv a_2 \ (mod \ b_2) \\\quad \quad \quad \vdots \\x \equiv a_n \ (mod \ b_n) \end{cases}
\]
其中\(b_1,b_2,\dots,b_n\)两两互质。
令\(m = \prod\limits_{i = 1}^n b_i\),\(M_i = \frac{m}{b_i}\),\(t_i\)是同余方程\(xM_i \equiv 1 \ (mod \ b_i)\)的一个解
那么上面那个方程组的解为\(\sum\limits_{i = 1}^{n} a_i M_i t_i\)。
证明:
考虑\(\sum\)中的一项\(i\),对于\(k = i\)显然有\(a_i M_i t_i \equiv a_k \ (mod \ b_k)\),若\(k \not = i\),则\(a_i M_i t_i \equiv 0 \ (mod \ b_k)\)(因为\(M_i\)是其他\(b\)的乘积)。
所以上面\(\Sigma\)中的\(n\)项各会满足一个方程,且不会对其他有影响,故\(x = \sum\limits_{i = 1}^{n} a_i M_i t_i\)是一组合法解。
证毕。
另外,\(x\)是在\(mod \ m\)意义下的解,即解集可以表示为\(\{x + km : k \in \Z\}\)。
\(Code\)
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll mult(ll a,ll b,ll c){ if (b>a) swap(a,b); ll ret=0; for (;b;b>>=1,a=a*2%c) if (b&1) ret=(ret+a)%c; return ret; } void exgcd(ll a,ll b,ll &x,ll &y){ if (b==0){x=1,y=0;return;} else{ exgcd(b,a%b,x,y); ll tmp=x; x=y; y=tmp-a/b*x; } } ll a[110],b[110]; int n; ll CRT(){ ll m=1; for (int i=1;i<=n;i++)m*=b[i]; for (int i=1;i<=n;i++) a[i]=(a[i]%m+m)%m; ll ans=0; for (int i=1;i<=n;i++){ ll Mi=m/b[i],t,tmp; exgcd(Mi,b[i],t,tmp); t=(t%m+m)%m; ans=(ans+mult(Mi,mult(t,a[i],m),m))%m; } return ans; } int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lld",&a[i]); for (int i=1;i<=n;i++) scanf("%lld",&b[i]); printf("%lld\n",CRT()); return 0; }
待填:扩展中国剩余定理 \(ExCRT\)
来源:https://www.cnblogs.com/wxq1229/p/12232491.html