1. 题目背景与需求分析
这道编程题源自GESP一级认证考试,题目描述为:小明需要购买文具,已知文具店里有三种文具,分别是铅笔、橡皮和笔记本。铅笔每支2元,橡皮每个1元,笔记本每本5元。现在给定小明拥有的钱数n(n≥1),要求计算出小明用这些钱恰好能买多少种不同的文具组合(每种文具可以买0个或多个)。
1.1 问题建模
这是一个典型的组合数学问题,可以抽象为:
给定三个正整数a=2,b=1,c=5,求非负整数解(x,y,z)的个数,使得2x + y + 5z = n成立。
这类问题在计算机科学中被称为线性丢番图方程,是算法竞赛和编程考试中的常见题型。解题关键在于如何高效枚举所有可能的组合情况。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路与算法设计
2.1 暴力枚举法
最直观的解法是三重循环枚举所有可能的购买组合:
python复制n = int(input())
count = 0
for x in range(n//2 + 1): # 铅笔最多买n//2支
for y in range(n + 1): # 橡皮最多买n个
for z in range(n//5 + 1): # 笔记本最多买n//5本
if 2*x + y + 5*z == n:
count += 1
print(count)
时间复杂度分析:
- 最外层循环次数:O(n/2)
- 中层循环次数:O(n)
- 内层循环次数:O(n/5)
- 总复杂度:O(n³)
虽然对于n≤100的小规模数据足够,但当n较大时效率会显著下降。
2.2 优化解法:双重循环
观察到当确定x和z后,y的值可以直接计算得出:
python复制n = int(input())
count = 0
for x in range(n//2 + 1):
for z in range(n//5 + 1):
remaining = n - 2*x - 5*z
if remaining >= 0:
count += 1
print(count)
优化效果:
- 减少一层循环
- 时间复杂度降为O
