中国剩余定理
对于一组同余方程,\(m_{1},m_{2}...m_{n}两两互质\)
\[
\left\{\begin{array}{l}{x \equiv a_{1}\left(\bmod m_{1}\right)} \\{x \equiv a_{2}\left(\bmod m_{2}\right)} \\{\cdots} \\{x \equiv a_{n}\left(\bmod m_{n}\right)}\end{array}\right.
\]
有整数解。并且在模\(M = m_{1}*m_{2}..m_{n}\)下的解是唯一的,解为
\[
\boldsymbol{x} \equiv\left(\boldsymbol{a}_{1} M_{1} M_{1}^{-1}+a_{2} M_{2} M_{2}^{-1}+\ldots+a_{k} M_{k} M_{k}^{-1}\right) \bmod 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 > 0? x:x + M;//x = 是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}不一定两两互质时\)
\(x = a_{1} + m_{1}x_{1}\\x = a_{2}+m_{2}x_{2}\)
那么有\(m_{1}x_{1}+m_{2}x_{2} = a_{2}-a_{1}\)
只需要求出一个最小的x使得\(x = a_{1}+m_{1}x_{1}=a_{2}+m_{2}x_{2}\)
即\(x_{1}和x_{2}尽可能小,利用扩展欧几里得求出最小x_{1},x_{2}然后带回去得到x的特解x'\)
\(x的通解一定是x'+lcm(m_{1}+m_{2})*k\)
那么
\[
\mathrm{x} \equiv x^{\prime}(\bmod l \operatorname{cm}(m 1, m 2))
\]
#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++){ ll c = ((a[i] - ans) % m[i] + m[i]) % m[i]; ex_gcd(M,m[i],d,x,y); //if(c % d)return -1;//不存在解的情况 ll mod = m[i]/d; x = mull(x,c/d,mod); ans += x * M; M *= mod; ans = (ans % M + M) % M; } return ans > 0?ans:ans + M;//注意ans是M倍数时输出M } 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; }
来源:https://www.cnblogs.com/Emcikem/p/12234167.html