浅谈 EXCRT
前言
我们发现,如果你会 EXCRT ,那么你可以通过 CRT 的板子,这不是一举两得?
如果你选择 EXCRT ,她的实用性比 CRT 要广,同时也很好写,所以可以推荐直接学 EXCRT。
正文
我们要解决这样一个问题:求解关于 \(x\) 的方程组
\[\begin{cases}
x\equiv b_1 \pmod {a_1} \\
x\equiv b_2 \pmod {a_2} \\
\dots \\
x\equiv b_n \pmod {a_n}
\end{cases}
\]
我们现在介绍 EXCRT 的做法(其实就是一个一个地合并)。
于是我们考虑如何将两个同余式合并成为一个同余式:
\[\begin{cases}
x\equiv B\pmod A \\
x\equiv b_i \pmod {a_i}
\end{cases}
\]
我们可以得到 \(x=B+mA=b_i-na_i\) ,移项得到 \(mA+na_i=b_i-B\),于是我们得到了一个不定方程,可以使用 exgcd 求解(同时也可以判断无解情况)
于是假设我们已经得到特解 \(m,n\)
我们可以得到通解:
\[\begin{cases}\large
M=m+\frac{a_i}{\gcd(A,a_i)}t \\\large
N=n-\frac{A}{\gcd(A,a_i)}t
\end{cases}
\]
将 \(M\) 带入 \(x=B+mA\) 得到 \(\large x=mA+B+\frac{a_i}{\gcd(A,a_i)}t\),得到合并后的同余式 \(\large x\equiv mA+B \pmod {\frac{a_i}{\gcd(a_i,A)}}\) .
于是不断合并即可,时间复杂度 \(O(n\log V)\) .
代码
ll A=a[1],B=b[1];
for(int i=2;i<=n;i++) {
ll m,n;ll d=exgcd(A,a[i],m,n);ll lcm=A*a[i]/d;
B=(B+(b[i]-B)/d*m*A%lcm+lcm)%lcm;
A=A*a[i]/d;
}
print(B);

浙公网安备 33010602011771号