【蓝桥杯】43689.包子凑数

题目描述

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

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

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

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

输入描述

第一行包含一个整数 𝑁 (1≤𝑁≤100)。

以下 N 行每行包含一个整数 𝐴𝑖 (1≤𝐴𝑖≤100)。

输出描述

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

输入输出样例

示例 1

输入

2

4

5
输出

6

样例说明

凑不出的数目包括:1, 2, 3, 6, 7, 11。

示例 2

输入

2

4

6
输出

INF

样例说明

所有奇数都凑不出来,所以有无限多个

题目分析

蓝桥杯官网上的讲解视频看得我头晕,还要这个定理,那个定理的,我们来尝试使用比较简单的方法来解决这个问题。

案例1:在案例1中 N = 2, 代表有两种笼子,A1 = 4,A2 = 5,问有多少个数是凑不出来的。

我们假设未知数为C,笼子的数量设为 X1 和 X2 ,那么就有等式 C = A1 × X1 + A2 × X2

其中 0 <= X1 < ∞ ,0 <= X2 < ∞ ,上面的那个等式不成立的次数,即为凑不出的个数。

观察一下当C 从 1 到 20 的情况,X1 和 X2 最小从0开始取值:

1 = 4 × ?+ 5 × ? 等式不成立;

2 = 4 × ?+ 5 × ? 等式不成立;

3 = 4 × ?+ 5 × ? 等式不成立;

4 = 4 × 1 + 5 × 0 等式成立;

5 = 4 × 0 + 5 × 1 等式成立;

6 = 4 × ?+ 5 × ? 等式不成立;

7 = 4 × ?+ 5 × ? 等式不成立;

8 = 4 × 2 + 5 × 0 等式成立;

9 = 4 × 1 + 5 × 1 等式成立;

10 = 4 × 0 + 5 × 2 等式成立;

11 = 4 × ? + 5 × ? 等式不成立;

12 = 4 × 3 + 5 × 0 等式成立;

13 = 4 × 2 + 5 × 1 等式成立;

14 = 4 × 1 + 5 × 2 等式成立;

15 = 4 × 0 + 5 × 3 等式成立;

16 = 4 × 4 + 5 × 0 等式成立;

17 = 4 × 3 + 5 × 1 等式成立;

18 = 4 × 2 + 5 × 2 等式成立;

19 = 4 × 1 + 5 × 3 等式成立;

20 = 4 × 5 + 5 × 0 等式成立;

案例2:在案例2中 N = 2, 代表有两种笼子,A1 = 4,A2 = 6,问有多少个数是凑不出来的。

1 = 4 × ?+ 6 × ? 等式不成立;

2 = 4 × ?+ 6 × ? 等式不成立;

3 = 4 × ?+ 6 × ? 等式不成立;

4 = 4 × 1 + 6 × 0 等式成立;

5 = 4 × ?+ 6 × ? 等式不成立;

6 = 4 × 0+ 6 × 1 等式成立;

7 = 4 × ?+ 6 × ? 等式不成立;

8 = 4 × 2 + 6 × 0 等式成立;

9 = 4 × ?+ 6 × ? 等式不成立;

10 = 4 × 1 + 6 × 1 等式成立;

11 = 4 × ? + 6 × ? 等式不成立;

12 = 4 × 3 + 6 × 0 等式成立;

13 = 4 × ?+ 6 × ? 等式不成立;

14 = 4 × 2+ 6 × 1 等式成立;

15 = 4 × ?+ 6 × ? 等式不成立;

16 = 4 × 4 + 6 × 0 等式成立;

17 = 4 × ?+ 6 × ? 等式不成立;

聪明的你应该看出一些规律了。

1, 如果A1 和 A2 ... An 有最大公约数,且最大公约数不为1,则题目有无数解,记作INF。

比如案例2中,4和6有最大公约数2,则所有的奇数都无法组合出来;

2,如果A1 和 A2 ... An 互质,就是说A1 和 A2 ... An 的公约数为1,则题目有解。

3,当有解的情况下(即为A1 和 A2 互质), 可以通过动态规划的方法来求解。定义一个布尔数组 d p dp dp ,用于记录能否凑出对应数量的包子,初始状态下 d p [ 0 ] = t r u e dp[0] = true dp[0]=true,表示可以凑出 0 个包子。

然后遍历每一种蒸笼的容量 A i A~i~ A i ,对于大于等于 A i A~i~ A i 的每个数量 j j j , 若 d p [ j − a [ i ] ] dp[j - a[i]] dp[j−a[i]] 为 t r u e true true ,则 d p [ j ] = t r u e dp[j] = true dp[j]=true 。即意味着能通过个 j − A i j - A~i~ j−A i 包子再加上一笼 A i A~i~ A i 的包子,可以凑出 j j j 个包子。

最后,统计数组 d p dp dp 中值为 f a l s e false false 的元素个数,该个数就是无法凑出的包子数量。

解题步骤

  1. 输入处理:读取输入的蒸笼种类数n和每种蒸笼的容量a[i]。
  2. 最大公约数计算:使用辗转相除法计算所有蒸笼容量的最大公约数gcd。如果gcd不为 1,输出INF并结束程序。
  3. 动态规划初始化:定义布尔数组dp并初始化为false,dp[0] = true。
  4. 动态规划更新:遍历每种蒸笼容量a[i],对j从a[i]到10000进行更新,若dp[j - a[i]]为true,则dp[j] =
    true。
  5. 结果统计:统计dp数组中值为false的个数并输出。

代码实现

python 复制代码
def gcd(a, b):
    while b!= 0:
        a, b = b, a % b
    return a

n = int(input())
a = [int(input()) for _ in range(n)]

# 计算所有数的最大公约数
g = a[0]
for i in range(1, n):
    g = gcd(g, a[i])

if g!= 1:
    print("INF")
else:
    dp = [False] * 10001
    dp[0] = True
    for i in a:
        for j in range(i, 10001):
            dp[j] = dp[j] or dp[j - i]
    print(sum([1 for i in range(10001) if not dp[i]]))
相关推荐
Python×CATIA工业智造2 分钟前
Frida RPC高级应用:动态模拟执行Android so文件实战指南
开发语言·python·pycharm
onceco32 分钟前
领域LLM九讲——第5讲 为什么选择OpenManus而不是QwenAgent(附LLM免费api邀请码)
人工智能·python·深度学习·语言模型·自然语言处理·自动化
狐凄1 小时前
Python实例题:基于 Python 的简单聊天机器人
开发语言·python
悦悦子a啊2 小时前
Python之--基本知识
开发语言·前端·python
笑稀了的野生俊4 小时前
在服务器中下载 HuggingFace 模型:终极指南
linux·服务器·python·bash·gpu算力
Naiva4 小时前
【小技巧】Python+PyCharm IDE 配置解释器出错,环境配置不完整或不兼容。(小智AI、MCP、聚合数据、实时新闻查询、NBA赛事查询)
ide·python·pycharm
路来了4 小时前
Python小工具之PDF合并
开发语言·windows·python
蓝婷儿5 小时前
Python 机器学习核心入门与实战进阶 Day 3 - 决策树 & 随机森林模型实战
人工智能·python·机器学习
AntBlack5 小时前
拖了五个月 ,不当韭菜体验版算是正式发布了
前端·后端·python
.30-06Springfield5 小时前
决策树(Decision tree)算法详解(ID3、C4.5、CART)
人工智能·python·算法·决策树·机器学习