题目大意
给你\(n\)个数\(a_1, a_2 ... a_n\), 要你求最大的正整数\(m\)使得方程\(a_1 x_1 + a_2 x_2 + ... + a_n x_n = m\)无非负整数解. 题目数据满足\(a_x\)为正整数且不大于\(256\), \(n \le 10\).
Solution
先看一个定理: 对于正整数\(p\), \(q\)满足\(gcd(p, q) = 1\), 我们有\(px + qy = n\)无非负整数解的最大正整数\(n\)为\(pq - p - q\). 证明如下:
我们首先利用反证法, 证明\(px + qy \ne pq - p - q\): 我们假设存在正整数\(x\)和\(y\)使得\(px + qy = pq - p - q\), 则有\[ px + qy = pq - p - q \\ p(x + 1) + q(y + 1) = pq \\ \because gcd(p, q) = 1且p | q(y + 1) \\ \therefore p | y + 1 \\ 同理, q | x + 1 \] 接着我们令\(y + 1 = pj\), \(x + 1 = qk\). 则有\[ pqk + qpj = pq \\ pq(j + k) = pq \] 注意到\(x, y \ge 0\), 我们有\(y + 1 \ge 1\)且\(x + 1 \ge 1\), 因而\(j \ge 1\)且\(k \ge 1\). 因而\(j + k \ge 2\), 因而假设不成立. 得证. 再证明当\(n \ge pq - p - q + 1\)时原方程总有非负整数解: 我们令\(n = pq - p - q + k\), 则根据扩展欧几里得定理, 方程\(pa + qb = k\)有整数解(其中\(a\)和\(b\)中必有一个为正, 一个为负). 我们假设\(a < 0 < b\), 调整\(a\)和\(b\)的值使得\(|a| < q\). 令此时的\(a\)和\(b\)分别为\(A\)和\(B\). 回到原方程\[ px + qy = pq - p - q + k \\ px + qy = pq - p - q + Ax + By \\ p(x + 1 - A) + q(y + 1 - B) = pq \] 根据前面的结论, 我们又有\[ p | y + 1 - B \\ q | x + 1 - A \] 因此我们令\[ j = \frac{x + 1 - A} q \\ k = \frac{y + 1 - B} p \] 则有\[ pq(i + j) = pq \\ i + j = 1 \] 不妨设\(i = 0\)且\(j = 1\), 则\[ \begin{cases} y + 1 - B= 0 \\ x + 1 - A = q \end{cases} \] 因而\[ y = B - 1 \\ x = A + q - 1 \] 由于\(B > 0\), 因而\(B - 1 \ge 0\); 根据之前定义, 我们又有\(|A| < q\), 因而\(A + q - 1 \ge 0\) 因而原方程必有非负整数解.好了, 现在考虑这道题怎么做233
注意到\(a\)值较小, 我们直接从0开始到\(256^2\)背包暴力即可. 我们注意到\(a\)之间并不一定互质, 但这并不影响我们枚举的范围.#include#include const int N = 10, LIM = 256;int a[N], f[LIM * LIM << 2];int main(){ int n; scanf("%d", &n); for(int i = 0; i < n; ++ i) scanf("%d", a + i); f[0] = 1; for(int i = 1; i < LIM * LIM << 2; ++ i) for(int j = 0; j < n; ++ j) if(i - a[j] >= 0 && f[i - a[j]]) f[i] = 1; int ans = 0; for(int i = 1; i < LIM * LIM << 2; ++ i) if(! f[i]) ans = i; printf("%d\n", ans > LIM * LIM ? 0 : ans);}