[学习笔记](扩展)中国剩余定理(CRT&exCRT)

数论杀我 如果有错欢迎指出qwq

中国剩余定理(CRT)

现在我们考虑一个问题,如何求解:

\[\begin{cases} x\equiv x_1\pmod{p_1}\\ x\equiv x_2\pmod{p_2}\\ ...\\ x\equiv x_n\pmod{p_n} \end{cases} \]

其中,\(p_1,p_2...p_n\)互质。看着就一脸懵逼,所以我们引入中国剩余定理(CRT)解决这个问题。我们假设:

\(M=p_1\times p_2\times...\times p_n\)

\(M_i=M/p_i\)

\(t_i=M_i^{-1}\pmod{p_i}\),即\(t_i\)\(M_i\)\(\pmod {p_i}\)意义下的逆元

所以可以得到\(x_i t_i M_i\equiv x_i \pmod {p_i}\)

又由于\(M_i\)包括了除了\(p_i\)的所有模数,我们可以知道,\(\forall j\in \{1,2...n\}\),且\(j\neq i\),都有\(x_it_iM_i\equiv0\pmod{p_j}\)

所以\(x=x_1t_1M_1+x_2t_2M_2+...+x_nt_nM_n\)满足\(\forall i\in \{1,2,..,n\}\)都有\(x_it_iM_i+\sum_{j\neq i}x_jt_jM_j\equiv x_i\pmod{p_i}\)

这说明\(x\)就是方程组的一个解。我们继续考虑,假设已经确定\(x_1、x_2\)是方程组的解,\(p_1,p_2...p_n\)互质,所以\(M\)整除\(x1-x2\)(别问我所以怎么来的我也不知道),所以不同的\(x\)之间一定相差\(M\)的倍数,最后我们就可以得到\(x\)的通项啦。

\(x=kM+\sum_{i=1}^nx_it_iM_i\),在\(\pmod{M}\)的情况下\(x=\sum_{i=1}^nx_it_iM_i\)

(证明过程眼熟吗,眼熟就是百度百科


扩展中国剩余定理

(了解完exCRT之后你会发现CRT不用学

很明显很难保证所有题目中\(p_1p_2...p_n\)互质,不互质就没法做了?当然不是,这个时候exCRT就出现了。

前置芝士:exgcd

扩展中国剩余定理简单来说就是合并同余式子的过程。我们单独拿出前两个式子:

\[\begin{cases} x \equiv x_1\pmod{p_1}\\ x \equiv x_2\pmod{p_2}\\ \end{cases} \]

把它转化一下形式,可以得到:

\[\begin{cases} x=x_1+k_1p_1\\ x=x_2+k_2p_2\\ \end{cases} \]

变形,得到\(x_1+k_1p_1=x_2+k_2p_2 \Rightarrow k_1p_1+(-k_2)p_2=x_2-x_1\),看起来很像exgcd?那尝试用exgcd求解,从这里我们可以知道,如果\(gcd(p_1,p_2)\nmid (x2-x1)\),那么此方程组无解(为什么?因为exgcd),所以我们先用exgcd求解\(k_1p_1+(-k_2)p_2=gcd(p_1,p_2)\),设这里得到的答案为\(T_1,T_2\),将exgcd求解的式子两边同乘\(\frac{x_2-x_1}{gcd(p_1,p_2)}\),就可以得到\(k_1=T_1\times \frac{x_2-x_1}{gcd(p_1,p_2)},k_2=T_2\times \frac{x_2-x_1}{gcd(p_1,p_2)}\),再带入原式,显然满足这两个等式的\(T_1、T_2\)不止一个,每一组\(T_1、T_2\)都对应着一个\(x\),每两个解的差\(\Delta\)一定是\(\frac{x_2-x_1}{gcd(p_1,p_2)}\times p_1、\frac{x_2-x_1}{gcd(p_1,p_2)}\times p_2\)的倍数,所以\(\Delta\)一定是\(\frac{p_1,p_2}{gcd(p_1,p_2)}=lcm(p_1,p_2)\)的倍数,所以\(x=k_1p_1+x_1+t\times lcm(p_1,p_2)\),以上两个同余式子就可以化简成为一个:\(x\equiv k_1p_1+x_1\pmod{lcm(p_1,p_2)}\)

同理,\(n\)个同余式子我们可以化简成一个,最后合并得到的答案就是\(x\)的通式啦
注意这里无解的情况是我们求两个模数的最大公约数时,如果这个模数不是1且这个模数不能整除\(x_1-x_2\),那么说明无解。

exCRT's Code

void excrt(){
	int lcm=mod[1],last_x=b[1];
	for(int i=2;i<=n;i++){
		int k=lcm,x,y,lcm_a=(b[i]-last_x%mod[i]+mod[i])%mod[i];
		int gcd=exgcd(lcm,mod[i],x,y);//x,y代表一组T1,T2
                if(lcm_a%gcd!=0){
			printf("-1\n");
			return 0;
		}
		int ls=lcm_a/gcd;
		x=(mul(x,ls,mod[i]/gcd)%(mod[i]/gcd)+(mod[i]/gcd))%(mod[i]/gcd);//k1
		ls=lcm/gcd;
		lcm=ls*mod[i];//保证了lcm中一定没有相同的因数 
		last_x=(last_x+mul(x,k,lcm))%lcm;
	}
	printf("%lld\n",(last_x%lcm+lcm)%lcm);
	return;
}

(至于为什么没有CRT的code,小编也不知道qwq,感觉exCRT可以做CRT的题吧)

posted @ 2020-08-12 21:30  蒟蒻zyx_qwq  阅读(155)  评论(0编辑  收藏  举报