重启usaco.
抽象出模型,可以发现是一个简单的完全背包问题,复杂度O(N^2+VN).需要考虑几种特殊情况:
(1)无解
当且仅当n个数中有一个数为1.
(2)惟一解
需要确定的是体积v的最大值.题解中是最大的两个数的最小公倍数,程序中使用最大数的平方,证明方法不知.
(3)无限解
n个数不互质
1/**//*
2ID: liuyupa1
3PROG: nuggets
4LANG: C++
5*/
6#include<stdio.h>
7int w[15] = {0}, f[66000] = {0};
8int p[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251};
9void swap(int *x, int *y){
10 int k = *x; *x = *y; *y = k;
11}
12int max(int x, int y){
13 return x>y ? x : y;
14}
15int main(){
16 FILE *fin, *fout;
17 fin = fopen("nuggets.in", "r");
18 fout = fopen("nuggets.out", "w");
19 int n, i, j;
20 fscanf(fin, "%d", &n);
21 for (i = 1; i <= n; i++) fscanf(fin, "%d", &w[i]);
22 for (j = 0; j < 54; j++){
23 int t = 0;
24 for (i = 1; i <= n; i++)
25 if (w[i] % p[j] == 0) t++;
26 if (t == n) {
27 fprintf(fout, "0\n", p[j]);
28 return 0;
29 }
30 }
31 for (i = 1; i < n; i++)
32 for (j = i+1; j <= n; j++)
33 if (w[i] > w[j]) swap(&w[i], &w[j]);
34 if (w[1] == 1){
35 fprintf(fout, "0\n", p[j]);
36 return 0;
37 }
38 for (i = 1; i <= n; i++)
39 for (j = 0; j <= w[n]*w[n]; j++)
40 if (j-w[i] >= 0)
41 f[j] = max(f[j], f[j-w[i]]+w[i]);
42 i = w[n-1]*w[n];
43 while (i > -1 && f[i] == i) i--;
44 fprintf(fout, "%d\n", i);
45 return 0;
46}
47