数论杀我如果有错欢迎指出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\)的通式啦
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
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的题吧)