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;
}
原文地址:https://www.cnblogs.com/hrj1/p/11566957.html