P2737 [USACO4.1]麦香牛块Beef McNuggets
题目描述
农夫布朗的奶牛们正在进行斗争,因为它们听说麦当劳正在考虑引进一种新产品:麦香牛块。奶牛们正在想尽一切办法让这种可怕的设想泡汤。奶牛们进行斗争的策略之一是“劣质的包装”。“看,”奶牛们说,“如果你只用一次能装3块、6块或者10块的三种包装盒包装麦香牛块,你就不可能满足一次只想买1、2、4、5、7、8、11、14或者17块麦香牛块的顾客了。劣质的包装意味着劣质的产品。”
你的任务是帮助这些奶牛。给出包装盒的种类数N(1<=N<=10)和N个代表不同种类包装盒容纳麦香牛块个数的正整数(1<=i<=256),输出顾客不能用上述包装盒(每种盒子数量无限)买到麦香牛块的最大块数。如果所有购买方案都能得到满足或者不存在不能买到块数的上限,则输出0。 不能买到的最大块数(倘它存在)不超过2,000,000,000。
输入格式
第1行: 包装盒的种类数N
第2行到N+1行: 每个种类包装盒容纳麦香牛块的个数
输出格式
输出文件只有一行数字:顾客不能用包装盒买到麦香牛块的最大块数或0(如果所有购买方案都能得到满足或者顾客不能买到的块数没有上限)。
输入输出样例
输入 #1
3 3 6 10
输出 #1
17
说明/提示
题目翻译来自NOCOW。
USACO Training Section 4.1
显然,如果我们令dp[i]表示能否凑出i个牛块。
则满足以下递推式
if(dp[i])dp[i+weight[x]]=true;
然后我们需要的就是确定容量。
然后有这样一个结论,
若p,q互质,则任意大于lcf(p,q)-p-q的数都能被p,q表示
然后dp就好~
完结撒花!
#include<cstdio> using namespace std; int gcd(int a,int b) { if(b==0)return a; else return gcd(b,a%b); } int lcf(int a,int b) { return a*b/gcd(a,b); } bool dp[80000]; int weight[10]; int n;int cont=0x3f3f3f3f; int res=0; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-'){ w=-1; } ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } int main(){ n=read(); for(int i=0;i<n;i++){ weight[i]=read(); } int g=weight[0]; for(int i=0;i<n;i++) { g=gcd(g,weight[i]); if(g==1)break; } if(g!=1) { printf("0");return 0; } for(int i=0;i<n;i++) { for(int j=0;j<=i;j++) { int t=lcf(weight[i],weight[j]); if(cont>t&&gcd(weight[i],weight[j])==1)cont=t; } } dp[0]=true; for(int i=0;i<n;i++) { for(int j=0;j<cont;j++) { if(dp[j]==true) { dp[j+weight[i]]=true; } } } for(int i=0;i<cont;i++) { if(dp[i]==false)res=i; } printf("%d",res); return 0; }