拓展中国剩余定理(exCRT)
Warning
本笔记没有处理无解的情况,需要注意的是当判断无解时,
虽然在必定有解的情况下可能也会出现这个问题,但是洛谷的模板题数据未能体现,导致模板错误
下面的模板已经订正
update 2023-07-18
算法分析
由于exCRT完美的平替了CRT的全部功能,故不再详细复习CRT的相关内容.
考虑如下同余方程组,
展开得,
该式子左侧类似裴蜀定理, 则存在
当
当
则特解
考虑由多个同余方程组成的方程组,上面通解可表达成
由此,以此从方程组中选出两个同余方程进行合并,显然不失一般性。
Code
点击查看代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e5 + 50;
typedef long long lld;
inline int read() {
register int w = 0, f = 1;
register char c = getchar();
while (c > '9' || c < '0') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
w = w * 10 + c - '0';
c = getchar();
}
return w * f;
}
int n;
lld a1, a2, m1, m2;
inline lld gcd(register lld a, register lld b) {
return (!b ? a : gcd(b, a % b));
}
inline lld mul(register lld a, register lld b, register lld p) {
lld ans = 0;
while (b) {
if (b & 1) ans = (ans + a) % p;
a = (a + a) % p;
b >>= 1;
}
return ans;
}
inline lld exgcd(register lld a, register lld b, lld &x, lld &y) {
if (!b) {
x = 1;
y = 0;
return a;
}
register lld g = exgcd(b, a % b, x, y);
register lld tmp = x;
x = y;
y = tmp - a / b * y;
return g;
}
int main(){
n = read();
scanf("%lld%lld", &m1, &a1);
for (register int i = 2; i <= n; ++i) {
scanf("%lld%lld", &m2, &a2);
register lld x, y;
register lld g = exgcd(m1, m2, x, y);
register lld res = ((a2 - a1) % m2 + m2) % m2;
if (res % g) {
printf("No Solution\n");
return 0;
}
register lld tmp = m1 / g * m2;
a1 = (a1 + mul(mul(res / g, x, tmp), m1, tmp) + tmp) % tmp;
m1 = tmp;
}
printf("%lld\n", a1);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?