ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

中国剩余定理和扩展中国剩余定理

2022-06-15 20:33:01  阅读:188  来源: 互联网

标签:剩余 frac pmod 定理 扩展 notag therefore ll equiv


中国剩余定理

定理

\[f(x)=\begin{cases}x \equiv a_1\pmod{m_1}\\x \equiv a_2\pmod{m_2}\\.\\.\\.\\x \equiv a_n\pmod{m_n}\end{cases}其中:m_1,m_2,m_3...,m_n 互质。 \]

且 \(M=\prod\limits_{i=1}^{n}m_i,M_i=\frac{M}{m_i},t_i=M_i^{-1}\),\(t_i\) 是在模 \(m_i\) 意义下的乘法逆元

则有最小解 \(x=(\sum\limits_{i=1}^{n}a_it_iM_i)\% M\)

证明

简易说明

\[\begin{align} \notag &M=\prod\limits_{i=1}^{n}m_i,M_i=\frac{M}{m_i},t_i=M_i^{-1}\\\notag &则可以构造出一解 x=a_1t_1M_1+a_2t_2M_2+..+a_nt_nM_n+kM=kM+\sum\limits_{i=1}^{n}a_it_iM_i,k\in Z\\\notag &\iff x_{min}=(\sum\limits_{i=1}^{n}a_it_iM_i)\% M \end{align} \]

证明 \(\sum\limits_{i=1}^{n}a_it_iM_i\) 是一个解

\[\begin{align} \notag &对于任意一个方程 x\equiv a_i\pmod{m_i}~来说\\\notag &x\% m_i=(a_1t_1M_1+a_2t_2M_2+..+a_nt_nM_n)\% m_i=a_it_iM_i\% m_i+\sum\limits_{j=1,j!=i}^{n}a_jt_jM_j\% m_i\\\notag &\because 当j!=i时m_i|M_j~~~~~~~注:这就是为什么必须要保证m互质,同时也证明了若互质则必定有解\\\notag &\therefore x_i\%m_i=a_it_iM_i\%m_i\\\notag &又\because t_iM_i\equiv 1\pmod{m_i}\\\notag &\therefore x_i\%m_i=a_i\%m_i\\\notag &\therefore x_i\equiv a_i\pmod{m_i} \end{align} \]

证明\(kM+\sum\limits_{i=1}^{n}a_it_iM_i,k\in Z\) 是一个解以及最小解

\[\begin{align} \notag &同上理,x=kM+\sum\limits_{i=1}^{n}a_it_iM_i,k\in Z 必然为方程的一个解\\\notag &\therefore 两个解相差 kM,k\in Z\\\notag &\therefore 对于非负数解集 Q 来说,是以 (\sum\limits_{i=1}^{n}a_it_iM_i)\% M 为首项,M为公差的等差数列 \end{align} \]

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn = 423;
ll int_maxn=1e9;
ll ll_maxn=1e18;
const ll mod=1e9+7;
const ll cs=998244353;
inline ll read_int(){
    ll a=0,f=0,g=getchar();
    while(g<'0'||g>'9'){if(g=='-') f=1;g=getchar();}
    while('0'<=g&&g<='9') a=a*10+g-'0',g=getchar();
    return f ? -a : a;
}
inline void write(ll s,bool f){
    int top=0,a[40];
    if(s<0) s=-s,putchar('-');
    while(s) a[++top]=s%10,s/=10;
    if(top==0) a[++top]=0;
    while(top) putchar(a[top]+'0'),top--;
    if(f) putchar('\n');
}

ll n;
ll A[maxn],M[maxn];
ll T[maxn],MM[maxn];
ll lin=1;

inline ll exgcd(ll a,ll b,ll & x,ll & y){
	if(b==0){x=1,y=0;return a;}
	ll gcd=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return gcd;
}

inline void read(){
	n=read_int();
	for(ll i=1;i<=n;i++) M[i]=read_int(),A[i]=read_int(),lin*=M[i];
	for(ll i=1;i<=n;i++) MM[i]=lin/M[i];
	ll ans=0;
	ll x,y;
	for(ll i=1;i<=n;i++) exgcd(MM[i],M[i],x,y),T[i]=(x%M[i]+M[i])%M[i];
	for(ll i=1;i<=n;i++) ans=(ans+(A[i]*T[i]*MM[i]%lin+lin)%lin)%lin;
	write(ans,1);
}

int main (){
	read();
}

扩展中国剩余定理

说明:中国剩余定理和扩展中国剩余定理只有名字相似罢了,思路基本不同!!

求解方程

\[f(x)=\begin{cases}x \equiv a_1\pmod{m_1}\\x \equiv a_2\pmod{m_2}\\.\\.\\.\\x \equiv a_n\pmod{m_n}\end{cases} 其中:m_1,m_2,m_3...,m_n$ 不互质 \]

思路推导

由于不保证 \(m_1,m_2,m_3..,m_n\) 互质,所以考虑将方程两个两个合并起来依次求解(可能无解)

\[\begin{align} \notag &取前两个方程进行合并 \begin{cases} x\equiv a_1\pmod{m_1} \\ x\equiv a_2\pmod{m_2}\end{cases}\\\notag &\therefore x=a_1+y_1m_1~~y_1\in Z\\ &\therefore x=a_2+y_2m_2~~y_2\in Z\\\notag &\Rightarrow y_2m_2-y_1m_1=a_1-a_2\\\notag &\therefore 当\gcd(m_1,m_2)|a_1-a_2 时有解,反之无解\\\notag &假设有解,则令 d=\gcd(m_1,m_2)\\\notag &\therefore \frac{m_2}{d}y_2-\frac{m_1}{d}y_1=\frac{a_1-a_2}{d}~~~~~~~~~注:裴储定理 \\\notag &\therefore \frac{m_2}{d}y_2\equiv \frac{a_1-a_2}{d}\pmod{\frac{m_1}{d}} \\\notag &\because \frac{m_2}{d}\perp\frac{m_1}{d} \therefore 令 inx[\frac{m2}{d}]为模\frac{m1}{d}意义下的乘法逆元~~~~~~~~~~~注:\frac{m_2}{d}\perp\frac{m_1}{d}是为了保证又乘法逆元 \\\notag &\therefore inx[\frac{m_2}{d}]\frac{m_2}{d}y_2\equiv \frac{a_1-a_2}{d}inx[\frac{m_2}{d}]\pmod{\frac{m_1}{d}} \Rightarrow y_2\equiv inx[\frac{m_2}{d}]\frac{a_1-a_2}{d}\pmod{\frac{m_1}{d}}\\ &\iff y_2=inx[\frac{m_2}{d}]\frac{a_1-a_2}{d}+y\frac{m_1}{d}\\ \notag &(1)(2)\Rightarrow x=a_2+m_2inx[\frac{m_2}{d}]\frac{a_1-a_2}{d}+y\frac{m_1m_2}{d} \\\notag &\therefore 方程~x\equiv a_2+m_2inx[\frac{m_2}{d}]\frac{a_1-a_2}{d} \pmod{\frac{m_1m_2}{d}} ~的解为上述方程组的解 \\\notag & 同理 x\equiv a_1+m_1inx[\frac{m_1}{d}]\frac{a_2-a_1}{d} \pmod{\frac{m_1m_2}{d}} 的解也为方程组的解 \end{align} \]

注意:在写代码时,注意变量名

CODE

#include<bits/stdc++.h>
#define ll __int128
using namespace std;
const ll maxn = 423;
ll int_maxn=1e9;
ll ll_maxn=1e18;
const ll mod=1e9+7;
const ll cs=998244353;
inline ll read_int(){
    ll a=0,f=0,g=getchar();
    while(g<'0'||g>'9'){if(g=='-') f=1;g=getchar();}
    while('0'<=g&&g<='9') a=a*10+g-'0',g=getchar();
    return f ? -a : a;
}
inline void write(ll s,bool f){
    ll top=0,a[40];
    if(s<0) s=-s,putchar('-');
    while(s) a[++top]=s%10,s/=10;
    if(top==0) a[++top]=0;
    while(top) putchar(a[top]+'0'),top--;
    if(f) putchar('\n');
}

ll n;
ll a1,a2,m1,m2;
ll ans;

inline ll exgcd(ll a,ll b,ll& x,ll& y){
	if(!b){x=1,y=0;return a;}
	ll gcd=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return gcd;
}

inline bool Extended_Chinese_remainder_theorem(){
	ll x,y;
	ll d=exgcd(m1,m2,x,y);
	ll c=a2-a1;
	if(c%d) return 0;
	x=((c/d*x)%(m2/d)+m2/d)%(m2/d);
	ll mod=m1/d*m2;
	a1=((m1*x+a1)%mod+mod)%mod;
	m1=mod;
	return 1;
}

inline void read(){
	n=read_int();
	a1=read_int(),m1=read_int();
	for(ll i=1;i<n;i++){
		a2=read_int(),m2=read_int();
		if(!Extended_Chinese_remainder_theorem()) {write(-1,0);return;}
	}
	write(a1%m1,1);
}

int main (){
	read();
}

总结有以下毒瘤之处:

  • 注意时刻保证\(a_1,m_1\) 处于正确的范围之中
  • 注意判断无解条件 \(a_2-a_1\% d~!=0\)
  • 多开 __int128
  • 一定要熟练运用裴储定理以及同余性质!

标签:剩余,frac,pmod,定理,扩展,notag,therefore,ll,equiv
来源: https://www.cnblogs.com/LQX-OI/p/16379701.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有