usaco 4.1.1

来源:互联网 发布:星星知多少疯狂动物园 编辑:程序博客网 时间:2024/05/16 13:49
Beef McNuggets
Hubert Chen

Farmer Brown's cows are up in arms, having heard that McDonalds is considering the introduction of a new product: Beef McNuggets. The cows are trying to find any possible way to put such a product in a negative light.

One strategy the cows are pursuing is that of `inferior packaging'. ``Look,'' say the cows, ``if you have Beef McNuggets in boxes of 3, 6, and 10, you can not satisfy a customer who wants 1, 2, 4, 5, 7, 8, 11, 14, or 17 McNuggets. Bad packaging: bad product.''

Help the cows. Given N (the number of packaging options, 1 <= N <= 10), and a set of N positive integers (1 <= i <= 256) that represent the number of nuggets in the various packages, output the largest number of nuggets that can not be purchased by buying nuggets in the given sizes. Print 0 if all possible purchases can be made or if there is no bound to the largest number.

The largest impossible number (if it exists) will be no larger than 2,000,000,000.

PROGRAM NAME: nuggets

INPUT FORMAT

Line 1:N, the number of packaging optionsLine 2..N+1:The number of nuggets in one kind of box

SAMPLE INPUT (file nuggets.in)

33610

OUTPUT FORMAT

The output file should contain a single line containing a single integer that represents the largest number of nuggets that can not be represented or 0 if all possible purchases can be made or if there is no bound to the largest number.

SAMPLE OUTPUT (file nuggets.out)

17
    一开始没读懂题意。题目意思是说:如果所有购买方案都能满足输出0;如果不存在不能购买块数上限,即有无数种购买方案不能满足,也输出0;否则,输出不能购买的最大块数。题目还指出,如果最大块数存在的话不超过2,000,000,000。这个数据实在太大!需要剪枝优化。其中涉及到一些数论的知识。
   有N中包装,分别为a1,a2,...,an。从小到大排列。如果所有购买方案都能满足,则a1=1;如果有无数种购买方案不能满足,则gcd(a1,a2,...,an)!=1,反之,如果存在最大块数,则gcd(a1,a2,...an)=1。所以首先可进行分类,对于存在最大块数的情况有下面的解决方案。
    先介绍数论里面的一个结论:如果a>0,b>0,gcd(a,b)=1则,对于任意的非负数x,y,a*x+b*y不能表示的最大值是a*b-a-b。
于是最大块数一定不超过an*(an-1)-an-(an-1)。而an最大为256,于是最坏情况的搜索量也只有256*255-256-255=64769。这个数据就很小了。剩下的工作就是从an*(an-1)-an-(an-1)开始记忆化搜索。
/*ID: fwj_ona1LANG: C++TASK: nuggets*/#include <stdio.h>#include <iostream>#include <memory.h>using namespace std;int n,num[10];int dp[65000];int gcd(int a,int b);int Dp(int k);int main (){freopen ("nuggets.in","r",stdin);    freopen ("nuggets.out","w",stdout);scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d",&num[i]);if(n==1){printf("0\n");return 0;}int flag;flag=gcd(num[0],num[1]);for(int i=2;i<n;i++){if(flag==1)break;flag=gcd(flag,num[i]);}if(flag!=1){printf("0\n");return 0;}memset(dp,-1,sizeof(dp));int min,max;min=max=num[0];for(int i=1;i<n;i++)if(max<num[i])max=num[i];elseif(min>num[i])min=num[i];if(min==1){printf("0\n");return 0;}for(int i=0;i<n;i++)dp[num[i]]=1;for(int i=1;i<min;i++)dp[i]=0;int ans=1;for(int i=max*max-3*max+1;i>min;i--){if(dp[i]!=-1)if(dp[i]==0){ans=i;break;}elsecontinue;Dp(i);if(dp[i]==0){ans=i;break;}}printf("%d\n",ans);return 0;}int gcd(int a,int b){while(1){a=a%b;if(a==0)return b;b=b%a;if(b==0)return a;}}int Dp(int k){if(dp[k]!=-1)return dp[k];dp[k]=0;for(int i=0;i<n;i++){if(k-num[i]>0){int flag=Dp(k-num[i]);if(flag==1)dp[k]=1;}}return dp[k];}


原创粉丝点击