【初等数论】中国剩余定理及其扩展

中国剩余定理(CRT)

“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?” ——《孙子算经》

定理内容

一次同余方程组 :

{ x ≡ a 1 ( m o d   m 1 ) x ≡ a 2 ( m o d   m 2 ) ⋯ x ≡ a n ( m o d   m n ) \left\{ \begin{array}{lcl} x≡a_{1} (mod\space m_{1})\\ x≡a_{2} (mod\space m_{2}) \\ \cdots \\ x≡a_{n} (mod\space m_{n}) \end{array} \right. xa1(mod m1)xa2(mod m2)xan(mod mn)

如果满足 m i m_{i} mi 两两互质,则在 m o d   M ( M = m 1 ⋅ m 2 ⋅ m 3 ⋯ m n ) mod\space M(M=m_{1}\cdot m_{2}\cdot m_{3}\cdots m_{n}) mod M(M=m1m2m3mn) 意义下,存在唯一解.

定理证明

构造解 M = m 1 ⋅ m 2 ⋅ m 3 ⋯ m n M=m_{1}\cdot m_{2}\cdot m_{3}\cdots m_{n} M=m1m2m3mn M i = M / m i M_{i}=M/m_{i} Mi=M/mi t i t_{i} ti M i M_{i} Mi m o d   m i mod\space m_{i} mod mi 意义下的乘法逆元, g c d ( M i , m i ) = 1 gcd(M_{i},m_{i})=1 gcd(Mi,mi)=1 .

x = ( ∑ i = 1 n a i t i M i ) x=(\sum\limits_{i=1}^na_{i}t_{i}M_{i}) x=(i=1naitiMi) ( m o d   M ) (mod\space M) (mod M)

带入验证,对于每一个一次同于方程 x ≡ a j ( m o d   m j ) x≡a_{j} (mod\space m_{j}) xaj(mod mj) .

i ≠ j i≠j i=j 时,一定有 m j   ∣   a i t i M i m_{j}\space |\space a_{i}t_{i}M_{i} mj  aitiMi a i t i M i   m o d   m j = 0 a_{i}t_{i}M_{i}\space mod\space m_{j}=0 aitiMi mod mj=0 .

i = j i=j i=j 时,一定有 a i t i M i = a j a_{i}t_{i}M_{i}=a_{j} aitiMi=aj a i t i M i   m o d   m j = a j a_{i}t_{i}M_{i}\space mod\space m_{j}=a_{j} aitiMi mod mj=aj .

由此,同余方程组成立 .

典型例题

【模板】中国剩余定理(CRT)/ 曹冲养猪

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=15;
namespace zyx_{

ll read(){
	ll x=0;int f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
void print(ll x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) print(x/10);
	putchar('0'+x%10);
	return ;
}
ll mul(ll a,ll b,ll mod){
	ll res=0;
	a%=mod;
	while(b){
		if(b&1) res=(res+a)%mod;
		a=(a+a)%mod;
		b>>=1;
	}
	return res;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(!b){
		x=1,y=0;
		return a;
	}
	ll d=exgcd(b,a%b,y,x);
	y-=(a/b)*x;
	return d;
}
ll inv(ll a,ll b){
	ll x,y;
	exgcd(a,b,x,y);
	return (x%b+b)%b;
}
ll n,M=1,ans,a[N],b[N];
int my_main(){
	n=read();
	for(int i=1;i<=n;i++)
		a[i]=read(),b[i]=read(),M*=a[i];
	for(int i=1;i<=n;i++){
		ll Mi=M/a[i];
		ll tmp=mul(b[i],Mi,M);
		tmp=mul(tmp,inv(Mi,a[i]),M);
		ans=(ans+tmp)%M;
	}
	print(ans);
	return 0;
}

}
int main(){
	zyx_::my_main();
	return 0;
}

扩展中国剩余定理(EXCRT)

中国剩余定理的局限性

中国剩余定理(CRT)不能解决模数不互质情况的模线性同余方程组:

a n s ≡ ∑ i = 1 n a i ⋅ M i ⋅ i n v ( M i , m i )   ( m o d   M ) ans≡ \sum\limits_{i=1}^na_{i}\cdot M_{i}\cdot inv(M_{i},m_{i})\space (mod\space M) ansi=1naiMiinv(Mi,mi) (mod M)

其中的 i n v ( M i , m i ) inv(M_{i},m_{i}) inv(Mi,mi) M i , m i M_{i},m_{i} Mi,mi 不互质的情况下,根本不存在。而只要有任意两个模数不互质,就会破坏掉整个解。

解决方案

扩展中国剩余定理的核心思想就是将两个同余方程组两两合并

对于两个同余方程:

{ x ≡ a 1 ( m o d   m 1 ) x ≡ a 2 ( m o d   m 2 ) \left\{ \begin{array}{lcl} x≡a_{1} (mod\space m_{1})\\ x≡a_{2} (mod\space m_{2}) \end{array} \right. {xa1(mod m1)xa2(mod m2)

可以将其转化为不定方程组:

{ x = k 1 m 1 + a 1 x = k 2 m 2 + a 2 \left\{ \begin{array}{lcl} x=k_{1}m_{1}+a_{1}\\ x=k_{2}m_{2}+a_{2} \end{array} \right. {x=k1m1+a1x=k2m2+a2

合并,移项后,得到新的不定方程:

k 1 m 1 − k 2 m 2 = a 2 − a 1 k_{1}m_{1}-k_{2}m_{2}=a_{2}-a_{1} k1m1k2m2=a2a1

由裴蜀定理得,当且仅当 g c d ( m 1 , m 2 )   ∣   ( a 2 − a 1 ) gcd(m_{1},m_{2})\space |\space (a_{2}-a_{1}) gcd(m1,m2)  (a2a1) 时,有解;

我们就能够根据扩展欧几里德算法计算出系数:

d = g c d ( m 1 , m 2 ) d=gcd(m_{1},m_{2}) d=gcd(m1,m2)

将方程左右两边同时除以 d d d ,得

m 1 d k 1 + m 2 d ( − k 2 ) = a 2 − a 1 d \frac{m_{1}}{d}k_{1}+\frac{m_{2}}{d}(-k_{2})=\frac{a_{2}-a_{1}}{d} dm1k1+dm2(k2)=da2a1

为了简化方程,令:

m 1 ′ = m 1 d k 1 , m 2 ′ = m 2 d k 1 , c = a 2 − a 1 d m_{1}^{'}=\frac{m_{1}}{d}k_{1},m_{2}^{'}=\frac{m_{2}}{d}k_{1},c=\frac{a_{2}-a_{1}}{d} m1=dm1k1,m2=dm2k1,c=da2a1

方程变为:

m 1 ′ k 1 + m 2 ′ ( − k 2 ) = c m_{1}^{'}k_{1}+m_{2}^{'}(-k_{2})=c m1k1+m2(k2)=c

其中 g c d ( m 1 ′ , m 2 ′ ) = 1 gcd(m_{1}^{'},m_{2}^{'})=1 gcd(m1,m2)=1 ,根据裴蜀定理,一定有:

m 1 ′ u + m 2 ′ v = 1 m_{1}^{'}u+m_{2}^{'}v=1 m1u+m2v=1

则通解:

k 1 = c u + t m 2 ′ , k 2 = − ( c v − t m 1 ′ )   ( t ∈ Z ) k_{1}=cu+tm_{2}^{'},k2=-(cv-tm_{1}^{'})\space (t\in Z) k1=cu+tm2,k2=(cvtm1) (tZ)

代回求 x x x

x = a 1 + k 1 m 1 = a 1 + ( c u + t m 2 ′ ) m 1 x=a_{1}+k_{1}m_{1}=a_{1}+(cu+tm_{2}^{'})m_{1} x=a1+k1m1=a1+(cu+tm2)m1

化简,得:

x = a 1 + c u ⋅ m 1 + t ⋅ m 1 m 2 d x=a_{1}+cu\cdot m_{1}+t\cdot \frac{m_{1}m_{2}}{d} x=a1+cum1+tdm1m2

x 0 = a 1 + c u ⋅ m 1 x_{0}=a_{1}+cu\cdot m_{1} x0=a1+cum1 ,则合并结果为:

x ≡ x 0   ( m o d   l c m ( m 1 , m 2 ) ) x≡x_{0}\space (mod\space lcm(m_{1},m_{2})) xx0 (mod lcm(m1,m2))

典型例题

【模板】扩展中国剩余定理(EXCRT)

#include<bits/stdc++.h>
using namespace std;
typedef __int128 ll;
const int N=1e5+5;
namespace zyx_{

ll read(){
	ll x=0;int f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
void print(ll x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) print(x/10);
	putchar(x%10+'0');
	return ;
}
ll n,A=1,B=0,x,y;
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(!b){
		x=1,y=0;
		return a;
	}else{
		ll d=exgcd(b,a%b,y,x);
		y-=a/b*x;
		return d;
	}
}
int my_main(){
	n=read();
	for(int i=1;i<=n;i++){
		ll a,b;
		a=read(),b=read();
		ll d=exgcd(A,a,x,y);
		x=(B-b)/d*x;
		B=B-A*x;
		A=a/d*A;
		B=(B%A+A)%A;
	}
	ll ans=(B%A+A)%A;
	print(ans);
	return 0;
}

}
int main(){
	zyx_::my_main();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值