拓展中国剩余定理(EXCRT)
普通的 CRT 只能处理模数两两互质的情况,而 EXCRT 可以求得任意情况下同余方程组的通解。
思想:把两个同余方程合并成一个,直到剩下一个。
考虑两个同余方程
则
这是一个经典的二元一次不定方程,用 exgcd 求出一个
定理:若
有特解 ,则其通解为 , 。
证明:首先,
这个问题等价于证明
假设有两个解
所以这两个同余方程可以合并为
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
inline __int128 read()
{
__int128 x=0,f=1;
char ch;
while(ch>'9'||ch<'0')
{
if(ch=='-')f=-1;
ch=getchar();
}
while('0'<=ch&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline void write(__int128 x)
{
if(x<0)putchar('-'),x=-x;
if(x>=10)write(x/10);
putchar(x%10+'0');
}
int n;
__int128 a[N], b[N];
typedef pair<__int128, __int128> pii;
queue<pii> q;
void exgcd(__int128 a, __int128 b, __int128 &x, __int128 &y) {
if (b == 0) {
x = 1, y = 0;
return ;
}
exgcd(b, a % b, x, y);
__int128 x0 = x, y0 = y;
x = y0;
y = x0 - (a / b) * y0;
return ;
}
__int128 gcd(__int128 a, __int128 b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
__int128 lcm(__int128 a, __int128 b) {
return a * b / gcd(a, b);
}
void chk() {
pii f1 = q.front();
q.pop();
pii f2 = q.front();
q.pop();
__int128 p1 = f1.first, m1 = f1.second, p2 = f2.first, m2 = f2.second;
if ((p2 - p1) % gcd(m1, m2) != 0) {
cout << "NIE\n";
exit(0);
}
__int128 g = gcd(m1, m2), A, B;
exgcd(m1 / g, m2 / g, A, B);
__int128 t = p1 + (p2 - p1) / g * A * m1 % lcm(m1, m2);
if (t >= 0)
q.push(make_pair(t, lcm(m1, m2)));
else {
t += lcm(m1, m2);
q.push(make_pair(t, lcm(m1, m2)));
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
b[i] = read();
a[i] = read();
q.push(make_pair(a[i], b[i]));
}
for (int i = 1; i < n; i++)
chk();
write(q.front().first);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!