USACO 4.1 Beef McNuggets(DP)

以前一次比赛中遇见过。一直以为价值为a和b的两种钱币,最大组不成的是a*b-a-b。。。后来发现前提是a和b两个是互质的。

知道这个结论,这个题目就转化为背包了。如何证明,我没想出来,也有点怀疑正确性。不过代码数据都过了。

 1 /*

 2       ID: cuizhe

 3       LANG: C++

 4       TASK: nuggets

 5 */

 6 #include <cstdio>

 7 #include <cstring>

 8 #include <iostream>

 9 #include <cmath>

10 #include <algorithm>

11 using namespace std;

12 int p[11];

13 int dp[256*256];

14 int gcd(int a,int b)

15 {

16     return b == 0 ? a:gcd(b,a%b);

17 }

18 int main()

19 {

20     int n,i,j,v,key,flag;

21     freopen("nuggets.in","r",stdin);

22     freopen("nuggets.out","w",stdout);

23     scanf("%d",&n);

24     for(i = 1;i <= n;i ++)

25     scanf("%d",&p[i]);

26     if(n == 1)

27     {

28         printf("%d\n",p[1]-1);

29         return 0;

30     }

31     sort(p+1,p+n+1);

32     key = p[1];

33     for(i = 2;i <= n;i ++)

34     key = gcd(key,p[i]);

35     if(key != 1)

36     {

37         printf("0\n");

38         return 0;

39     }

40     flag = 1;

41     for(i = 1;i <= n&&flag;i ++)

42     {

43         for(j = i+1;j <= n&&flag;j ++)

44         {

45             if(gcd(p[i],p[j]) == 1)

46             {

47                 v = p[i]*p[j] - 1

48                 flag = 0;

49             }

50         }

51     }

52     dp[0] = 1;

53     for(i = 1;i <= n;i ++)

54     {

55         for(j = p[i];j <= v;j ++)

56         {

57             dp[j] += dp[j-p[i]];

58         }

59     }

60     for(i = v;i >= 1;i --)

61     {

62         if(dp[i] == 0) break;

63     }

64     printf("%d\n",i);

65     return 0;

66 }

 

你可能感兴趣的:(USACO)