欧几里得+完全背包 蒸包子凑数

来源:互联网 发布:可视化编程软件 知乎 编辑:程序博客网 时间:2024/06/09 16:49
小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有N种蒸笼,其中第i种蒸笼恰好能放Ai个包子。每种蒸笼都有非常多笼,可以认为是无限笼。
每当有顾客想买X个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有X个包子。比如一共有3种蒸笼,分别能放3、4和5个包子。当顾客想买11个包子时,大叔就会选2笼3个的再加1笼5个的(也可能选出1笼3个的再加2笼4个的)。
当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有3种蒸笼,分别能放4、5和6个包子。而顾客想买7个包子时,大叔就凑不出来了。

小明想知道一共有多少种数目是包子大叔凑不出来的。





首先如果N种蒸笼的包子数是互质的,那么是有限的。如果不是互质的,那么直接输出INF即可。


如果是互质的,我们dp【0】=1.

之后用n个包子暴力遍历1-10000,看看哪些数能能凑出来即可


#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int dp[10000];
bool judge(int x,int y)
{
    int t;
    while(y>0)
    {
        t=x%y;
        x=y;
        y=t;
    }
    if(x==1)
        return true;
    return false;
}
int main()
{
    int a[200],n,i,j,res,mark;


    while(scanf("%d",&n)!=EOF)
    {
        res=0;
        mark=0;
        memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                if(judge(a[i],a[j]))
                {
                    mark=1;
                    break;
                }
            }
            if(mark==1)
                break;
        }
        if(mark!=1)
        {
            printf("INF\n");
            continue;
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j+a[i]<=10000;j++)
            {
                if(dp[j])
                {
                    dp[j+a[i]]=true;
                }
            }
        }
        int cnt=0;
        for(int i=1;i<=10000;i++)
        {
            if(!dp[i])
            {
                cnt++;
            }
        }
        cout<<cnt<<endl;
    }
    return 0;
}

原创粉丝点击