USACO 4.1.1 麦香牛块 Beef McNuggets

题目大意

给你\(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 <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\n", ans > LIM * LIM ? 0 : ans);
}

posted @ 2017-09-02 16:43  Zeonfai  阅读(223)  评论(0编辑  收藏  举报