浅谈 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);
posted @ 2026-08-10 17:28  tyccyt  阅读(7)  评论(0)    收藏  举报