Loading [MathJax]/jax/element/mml/optable/BasicLatin.js

关于 exgcd 求得特解的数值范围

upd 12.6:修复了一个伪证的地方()

int exgcd(int a, int b, int &x, int &y) {
	if(!b) return x = 1, y = 0, a;
	int d = exgcd(b, a % b, y, x);
	return y -= a / b * x, d;
}

以前我写 int 的 exgcd,总是怕爆 int#define int long long,因为看上去没有任何证据说明 exgcd 得到的特解绝对值不会很大。以及如果系数是 long long 的话,那甚至不确定要不要开 __int128_t

事实上,我们可以证明 ax+by=gcd 由 exgcd 解出的特解保证了 x 绝对值最小。以下设 a' = \dfrac a d, b' = \dfrac b d

  • b = 0x = 1, y = 0 显然满足条件。
  • 否则,x 为所有解中绝对值最小的显然当且仅当 |x| \leq \dfrac 1 2 |b'|。考虑归纳:b \mid a 是递归的倒数第二层,当作边界验证,解为 x = 0, y = 1,此时 |x| = 0 显然满足条件。对于 b \nmid a,按照 exgcd 的代码递归到了 by_0 + (a \bmod b)x_0 = d,得到了使得 |y_0| 最小的解,有 |y_0| \leq \dfrac 1 2 \left|\dfrac{a \bmod b} d\right|;而 x 是直接继承 x_0 的,所以有 x = x_0 = \dfrac{d - by_0}{a \bmod b},那么显然 |x| \leq \left|\dfrac d{a \bmod b}\right| + \left|\dfrac{b \cdot \frac 1{2d}(a \bmod b)}{a \bmod b}\right| \leq \left|\dfrac d{a \bmod b}\right| + \left|\dfrac 1 2 b'\right|。由于 \gcd(a \bmod b, a) = d(且 a \bmod b \neq 0),必定有 a \bmod b \geq d,于是 \left|\dfrac d{a \bmod b}\right| \leq 1。此时如果有 \mathrm{LHS} < \dfrac 1 2 就直接证毕了好吧。由于 d \mid a \bmod b,现在只要稍微考虑一下 =\dfrac 1 2=1 的情况。
    • \mathrm{LHS} = 1,也就是 |d| = |a \bmod b|,这显然是倒数第三轮递归,手动模拟得到 x = 1,而不可能有 b' = 0(这样一定有 b = 0,这是最后一层)或 b' = \pm1|b| = |d| = |a \bmod b|,与 |a \bmod b| < |b| 矛盾),所以 |b'| \geq 2,也得到 |x| \leq \dfrac 1 2 |b'|
    • \mathrm{LHS} = \dfrac 1 2,那么 |d| = \dfrac 1 2 |a \bmod b|,即 |a \bmod b| = 2|d|。从 a, b 往下手动模拟 exgcd(绝对值相等视为相等):a, b\to b, 2d,下一步需要考虑 b \bmod 2d 等于多少。显然只可能等于 0d,如果等于 0 的话就有 \gcd(a, b) = 2d 了,矛盾,所以只可能等于 d。于是 \to 2d, d \to d, 0,发现这是倒数第四轮。手动模拟得到 |x| = \left\lfloor\left|\dfrac{b}{2d}\right|\right\rfloor,这不完美了吗,直接证毕了。

那么 y 的情况呢?注意到当 a = b 时,exgcd 得到解为 x = 0, y = 1,不用愁;而 a \neq b 时,解 ax + by = dby + ax = d 中恰好有一个的第一步是 swap(a, b),这使得两者解得的 (x, y) 相等,所以在 |x| 取得最小的同时,|y| 也取得最小。这意味着(除了 ab 等于 0 或者 a = b 的极端情况)同时有 |x| \leq \dfrac 1 2 |b|, |y| \leq \dfrac 1 2 |a|,这样不开 long long 都不带怕的。

posted @   ycx060617  阅读(1284)  评论(2编辑  收藏  举报
编辑推荐:
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
· 用纯.NET开发并制作一个智能桌面机器人:从.NET IoT入门开始
· 一个超经典 WinForm,WPF 卡死问题的终极反思
· ASP.NET Core - 日志记录系统(二)
阅读排行:
· 在外漂泊的这几年总结和感悟,展望未来
· 博客园 & 1Panel 联合终身会员上线
· 支付宝事故这事儿,凭什么又是程序员背锅?有没有可能是这样的...
· https证书一键自动续期,帮你解放90天限制
· 在 ASP.NET Core WebAPI如何实现版本控制?
历史上的今天:
2020-12-03 CF997C - Sky Full of Stars 题解
点击右上角即可分享
微信分享提示