题目大意
给你(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
e pq - p - q): 我们假设存在正整数(x)和(y)使得(px + qy = pq - p - q), 则有
接着我们令(y + 1 = pj), (x + 1 = qk). 则有
注意到(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).
回到原方程
根据前面的结论, 我们又有
因此我们令
则有
不妨设(i = 0)且(j = 1), 则
因而
由于(B > 0), 因而(B - 1 ge 0);
根据之前定义, 我们又有(|A| < q), 因而(A + q - 1 ge 0)
因而原方程必有非负整数解.
好了, 现在考虑这道题怎么做233
注意到(a)值较小, 我们直接从0开始到(256^2)背包暴力即可.
我们注意到(a)之间并不一定互质, 但这并不影响我们枚举的范围.
#include <cstdio>
#include <cctype>
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
", ans > LIM * LIM ? 0 : ans);
}