【蓝桥杯】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 dp0 = true dp0=true,表示可以凑出 0 个包子。

然后遍历每一种蒸笼的容量 A i A~i~ A i ,对于大于等于 A i A~i~ A i 的每个数量 j j j , 若 d p j − a \[ i ] dpj - a\[i] dpj−a\[i] 为 t r u e true true ,则 d p j = t r u e dpj = true dpj=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和每种蒸笼的容量ai
  2. 最大公约数计算:使用辗转相除法计算所有蒸笼容量的最大公约数gcd。如果gcd不为 1,输出INF并结束程序。
  3. 动态规划初始化:定义布尔数组dp并初始化为false,dp0 = true。
  4. 动态规划更新:遍历每种蒸笼容量ai,对j从ai到10000进行更新,若dpj - a\[i]为true,则dpj =
    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]]))
相关推荐
荷蒲1 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)2 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机2 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor6923 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy4 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽4 小时前
真实即粗糙,光滑是伪造
人工智能·python
一次旅行4 小时前
Attention机制从数学到工程:拆解缩放点积+多头注意力|附可运行PyTorch实现与踩坑指南
人工智能·pytorch·python
泡干脆面就番茄4 小时前
NumPy 科学计算完全指南:从数组创建到广播机制
python·numpy
denggun123455 小时前
信号量(DispatchSemaphore vs AsyncSemaphore)、swift协作式线程池 and python信号量
开发语言·python·swift
起光5 小时前
Python类与对象(一)
python