同余方程
线性(一次)同余方程
--> -> ,求的最小非负整数解。
扩展欧几里得算法
Bezout定理:, 满足
推导证明:
当递归到边界时,,显然有->令.
考虑递归返回过程,.假设存在x,y满足,因为,所以有,那么新的一组解为
对于更一般的情况,,当且仅当,方程有整数解。这时,只需给乘上即可。
更进一步,方程的通解表示为
证明:
inline int exgcd(int a, int b, int& x, int& y)//a*x + b*y = 1;
{
if (b == 0) { x = 1, y = 0; return a; }
int gcd = exgcd(b, a % b, x, y);
int z = x;
x = y, y = z - a / b * y;
return gcd;
}
inline int exgcd(int a, int b, int& x, int& y)//a*x + b*y = 1;
{
if (b == 0) { x = 1, y = 0; return a; }
int gcd = exgcd(b, a % b, y, x);//直接交换传参
y -= a / b * x;
return gcd;
}
inline int solve(int a, int b, int c)//a*x + b*y = c;
{
int x, y, g = exgcd(a, b, x, y);
if (c % g) return -1;//无解
a /= g, b /= g, c /= g;
//只要求x为最小非负整数解,而y可以为负数
x = (x * c % b + b) % b;
return x;
//x和y都要求为非负整数解
while (x > 0 || y < 0) x -= b, y += a;
x = -x, y = y;
}
高次同余方程
。互质,求解的最小非负整数解。
BSGS(Baby Step, Giant Step)算法
设,其中,则方程变为,进一步有。
对于所有的,把全部插入表,枚举,计算出,在表中查找,如果有,更新答案。最优时间复杂度为,为O()。
int BSGS(int a, int b, int p)//a^x≡b (mod p)
{
map <int, int> hash; hash.clear();//多次调用时,把map定义放在外面
b %= p;
int t = sqrt(p) + 1;
for (int j = 0; j < t; ++j) hash[b * qpow(a, j, p) % p] = j;
a = qpow(a, t, p);
if (a == 0) return b == 0 ? 1 : -1;
for (int i = 0; i <= t; ++i)
{
int val = qpow(a, i, p);
int j = hash.find(val) == hash.end() ? -1 : hash[val];
if (j >= 0 && i * t - j >= 0) return i * t - j;
}
return -1;//无解
}
一元线性同余方程组
中国剩余定理(物不知数)
当两两互质时,设是线性同余方程的一个解,也就是在意义下的逆元。那么在模有唯一解,有通解
证明
对于所有,因为,所以因数中包含,所以,也即。因为,所以,那么。同理可知满足所有个方程,解成立。
int CRT(int n, int a[], int m[])//中国剩余定理
{
int M = 1, ans = 0;
for (int i = 1; i <= n; ++i) M *= m[i];
for (int i = 1; i <= n; ++i)
{
int c = M / m[i], t, y;//除m[i]以外所有模数的倍数
exgcd(c, m[i], t, y);//c*t≡1(mod m[i])
ans += a[i] * c * t % M;//∑ a[i]*c[i]*t[i]
ans = (ans % M + M) % M;
}
return ans;
}
扩展中国剩余定理(模数不互质)
先来考虑只有两个方程的情况。设方程分别是,则得到不定方程。
移项得,首先当,方程无解;否则,可以得到一组可行解。令,合并得到同余方程,多个方程的话两两合并即可。
int calc(int a, int b, int c)//ax+by=c
{
int x, y, d = exgcd(a, b, x, y);
if (c % d) return -1;
a /= d, b /= d, c /= d;
return (x * c % b + b) % b;
}
int EXCRT(int n, int a[], int m[])//扩展中国剩余定理
{
int M = 1, ans = 0;
for (int i = 1; i <= n; ++i)
{
int x = calc(M, m[i], a[i] - ans);//M*x≡a[i]-ans(mod m[i])
if (x == -1) return -1;//判断无解
ans += x * M;//∑ ans+x[i]*M
M = lcm(M, m[i]);//更新前i个数的lcm
ans = (ans % M + M) % M;
}
return ans;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话