洛谷P8646 [蓝桥杯 2017 省 AB] 包子凑数

题目描述

小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有 NN 种蒸笼,其中第 ii 种蒸笼恰好能放 A_iAi​ 个包子。每种蒸笼都有非常多笼,可以认为是无限笼。

每当有顾客想买 XX 个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有 XX 个包子。比如一共有 33 种蒸笼,分别能放 33 、 44 和 55 个包子。当顾客想买 1111 个包子时,大叔就会选 22 笼 33 个的再加 11 笼 55 个的(也可能选出 11 笼 33 个的再加 22 笼 44 个的)。

当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有 33 种蒸笼,分别能放 44 、 55 和 66 个包子。而顾客想买 77 个包子时,大叔就凑不出来了。

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

输入格式

第一行包含一个整数 NN。(1 \le N \le 100)(1≤N≤100)。

以下 NN 行每行包含一个整数 A_iAi​。(1 \le A_i \le 100)(1≤Ai​≤100)。

输出格式

一个整数代表答案。如果凑不出的数目有无限多个,输出 INF

输入输出样例

输入 #1复制

2  
4  
5  

输出 #1复制

6

输入 #2复制

2  
4  
6   

输出 #2复制

INF

说明/提示

对于样例 11,凑不出的数目包括:1,2,3,6,7,111,2,3,6,7,11。

对于样例 22,所有奇数都凑不出来,所以有无限多个。

蓝桥杯 2017 省赛 A 组 H 题。

#include <stdio.h>
#include <string.h>
#define N 100001
int gcd(int a, int b)
{
 return b == 0 ? a : gcd(b, a%b);
}
  //返回多个数的最大公约数;
int max(int a,int b)
{
 return a>=b?a:b;
}
  //比较大小;
int main()
{
 int w[N];
 int n;
 int dp[N];
 memset(dp,0,sizeof(dp));
  //把dp数组赋值为0;
 scanf("%d",&n);
 for(int i=1;i<=n;i++)
  {
   scanf("%d",&w[i]);
  }
  //输入每笼包子数目;
 int g = w[1];
    for(int i = 2 ; i <= n ; i ++)
        g = gcd(g,w[i]);
    if(g != 1)
    {
        printf("INF\n");
    }
     //输出INF的情况;
    else
 {
 dp[0] = 1;
  for(int i=1;i<=n;i++)
   for(int j=w[i];j<N;j++)
       dp[j]=max(dp[j],dp[j-w[i]]);
       //背包问题转移方程变形;
 int cnt = 0;
 for (int i = 1; i < N; i++)
  if (dp[i]==0)
   cnt++;
   
 printf("%d",cnt);
 }
 return 0;
}

理解:这道题首先要判断这些蒸笼的包子数的最小公约数,显然,如果最小公约数是1,包子数必然只能取到他们的倍数,则必然有无穷个无法取到。然后运用背包问题转移方程,先对一个数组赋值为0.然后分别对每一种蒸笼进行判断,如果是其倍数,则把数组赋值为1,最后再进行判断,若为0的包子数就是取不到的

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值