专栏文章

P4549 题解

P4549题解参与者 4已保存评论 4

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
4 条
当前快照
1 份
快照标识符
@mipaxewi
此快照首次捕获于
2025/12/03 09:01
3 个月前
此快照最后确认于
2025/12/03 09:01
3 个月前
查看原文
更佳的阅读体验:洛谷 P4549 题解

算法介绍

给定一个长度为 nn 的整数序列 AA 和一个待定整数序列 XX,求 S=i=1nAi×XiS = \sum \limits_{i = 1}^{n} A_i \times X_i 在正数范围内的最小值。
看上去似乎有点无从下手。
那先从简单的开始!我们来考虑 n=2n = 2 的情况,此时问题简化为求 A1X1+A2X2A_1 X_1 + A_2 X_2 的最小值。
如果我们设 a,ba, b 是不全为 00 的整数,那么有裴蜀定理(Bézout's Lemma):
  • 对于任意整数 x,yx, y,有 gcd(a,b)(ax+by)\gcd (a, b) \mid (ax + by)
  • 存在整数 x,yx, y,使得 ax+by=gcd(a,b)ax + by = \gcd (a, b)
因此,ax+byax + by 的最小正整数值显然是 gcd(a,b)\gcd (a, b)。上述问题的答案就是 gcd(A1,A2)\gcd(A_1, A_2)
那么,当 n3n \ge 3 呢?我们尝试推广裴蜀定理。
假设有三个整数 a,b,ca, b, c。我们首先对前两个数应用裴蜀定理,存在整数 x1,x2x_1, x_2,使得 ax1+bx2=gcd(a,b)ax_1 + bx_2 = \gcd (a, b)。接下来,将这个结果与第三个数 cc 结合,即存在整数 k,x3k, x_3,使得 gcd(a,b)×k+cx3=gcd(gcd(a,b),c)\gcd (a, b) \times k + cx_3 = \gcd( \gcd(a, b), c)
我们知道,最大公约数有性质:gcd(a,b,c)=gcd(gcd(a,b),c)\gcd (a, b, c) = \gcd (\gcd(a, b), c),因此存在整数组合使得 ax1+bx2+cx3=gcd(a,b,c)ax_1 + bx_2 + cx_3 = \gcd(a, b, c),且不存在更小的正数解。
这样推广下去,最终无论 nn 的大小,问题的最小正数解都是所有 AiA_i 的最大公约数的绝对值。因此,我们只需要计算整个序列 AA 的最大公约数,并取其绝对值即可。

正确性证明

我们设 a,ba, b 是不全为 00 的整数,那么一定有 gcd(a,b)a\gcd(a, b) \mid agcd(a,b)b\gcd(a, b) \mid b。设 x,yx, y 为整数,则有 gcd(a,b)ax\gcd(a, b) \mid axgcd(a,b)by\gcd(a, b) \mid by,因此 gcd(a,b)(ax+by)\gcd(a, b) \mid (ax + by)
对于定理的第二点,若 aabb 任意一个等于 00,则 gcd(a,b)\gcd(a, b) 的值为非零数的值,此时定理显然成立。
ab0ab \neq 0,由于 gcd(a,b)=gcd(a,b)\gcd(a, b) = \gcd(a, -b),我们不妨设 a,ba, b 都大于 00aba \ge b,且有 gcd(a,b)=d\gcd(a, b) = d
ax+by=dax + by = d,两边同时除以 dd,得到 a1x+b1y=1a_1x + b_1y = 1,其中 a1,b1a_1, b_1 互质。接下来证明 a1x+b1y=1a_1x + b_1y = 1
我们先来回顾一下辗转相除法:gcd(a,b)gcd(b,amodb)\gcd(a, b) \rightarrow \gcd(b, a \bmod b) \rightarrow \cdots。我们把模出来的数记作 rr,则有:
gcd(a1,b1)=gcd(b1,r1)=gcd(r1,r2)==gcd(rn1,rn)=1\gcd(a_1, b_1) = \gcd(b_1, r_1) = \gcd(r_1, r_2) = \cdots = \gcd(r_{n - 1}, r_n) = 1
把辗转相除法中的运算展开成带余除法,得到:
a1=q1b1+r1(0r1<b1)b1=q2r1+r2(0r2<r1)r1=q3r2+r3(0r3<r2)rn3=qn1rn2+rn1rn2=qnrn1+rnrn1=qn+1rn\begin{align*} a_1 & = q_1b_1 + r_1 & (0 \le r_1 < b_1) \\ b_1 & = q_2r_1 + r_2 & (0 \le r_2 < r_1) \\ r_1 & = q_3r_2 + r_3 & (0 \le r_3 < r_2) \\ & \cdots & \\ r_{n - 3} & = q_{n - 1}r_{n - 2} + r_{n - 1} & \\ r_{n - 2} & = q_nr_{n - 1} + r_n & \\ r_{n - 1} & = q_{n + 1}r_n \end{align*}
我们令辗转相除法在除到互质的时候退出,则 rn=1r_n = 1,所以有:
rn2=qnrn1+1r_{n - 2} = q_nr_{n - 1} + 1
即:
1=rn2qnrn11 = r_{n - 2} - q_nr_{n - 1}
用倒数第三个式子 rn1=rn3qn1rn2r_{n - 1} = r_{n - 3} - q_{n - 1}r_{n - 2} 代入上式,得:
1=(1+qnqn1)rn2qnrn31 = (1 + q_nq_{n - 1}) r_{n - 2} - q_nr_{n - 3}
然后用同样的办法逐个地消去 rn2,,r1r_{n - 2}, \cdots, r_1,即可证得 1=a1x+b1y1 = a_1x + b_1y

代码实现

CPP
#include <iostream>
#include <algorithm>
using namespace std;

int n, a, ans;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cin >> n >> a;
    ans = a;
    for (int i = 2; i <= n; ++i)
        cin >> a, ans = __gcd(ans, abs(a));
    cout << ans << '\n';
    return 0;
}

评论

4 条评论,欢迎与作者交流。

正在加载评论...