/*
中国剩余定理
有这么一系列同余方程组
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;
}
中国剩余定理的详细探讨
最新推荐文章于 2023-07-02 18:34:05 发布