1. 问题背景与需求分析
洛谷B2020分糖果问题是一个经典的编程入门题目,主要考察对循环和取余运算的基本理解。题目通常描述为:有n个小朋友围成一圈分糖果,从第一个小朋友开始依次分发,每次发一颗,直到发完k颗糖为止。要求确定最后一块糖发给了哪个小朋友。
这个问题看似简单,但蕴含着几个关键编程概念:
- 循环分发过程的模拟
- 取余运算在循环中的应用
- 边界条件的处理
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心解决思路
2.1 取余运算的本质
取余运算(%)是这个问题的核心解法。其数学本质是:
- 对于正整数a和b,a % b的结果范围是0到b-1
- 当a是b的整数倍时,a % b = 0
- 这个特性正好对应了"循环计数"的需求
2.2 解题公式推导
直接解法公式:
最后得到糖果的小朋友编号 = (k-1) % n + 1
推导过程:
- 小朋友编号是1到n,而取余结果是0到n-1
- 所以需要先减1再取余,最后加1调整
- 这样当k=1时得到1,k=n时得到n,k=n+1时又回到1
3. 代码实现与验证
3.1 C++实现示例
cpp复制#include <iostream>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
cout << (k-1)%n + 1 << endl;
return 0;
}
3.2 Python实现示例
python复制n, k = map(int, input().split())
print((k-1)%n + 1)
3.3 边界测试用例
验证几个关键情况:
- n=5, k=1 → 输出1
- n=5, k=5 → 输出5
- n=5, k=6 → 输出1
- n=5, k=11 → 输出1
4. 常见误区与注意事项
4.1 新手常见错误
-
直接使用k%n:
- 当k是n的倍数时会得到0,不符合编号要求
- 例如n=3,k=3时,3%3=0,但应该输出3
-
忘记处理输入:
- 直接从命令行参数读取而不用cin/input
- 没有考虑多组输入的情况
-
过度复杂化:
- 使用循环模拟分发过程
- 使用数组存储每个小朋友的糖果数
4.2 性能考量
虽然这个问题用O(1)的公式解法最优,但理解其与循环解法的关系很重要:
- 循环解法时间复杂度O(k)
- 公式解法时间复杂度O(1)
- 当k很大时(如1e9),循环解法会超时
5. 问题扩展与变种
5.1 约瑟夫问题
这是分糖果问题的经典变种:
- 小朋友围成一圈,从1开始报数
- 报到m的出局,下一位从1重新报数
- 求最后剩下的人的编号
5.2 其他变种
- 每次发的糖果数递增
- 不同小朋友有不同的得糖概率
- 考虑糖果种类不同
6. 教学建议
对于编程初学者,建议分步骤理解:
- 先用小数据手工模拟分发过程
- 观察编号变化的规律
- 发现循环与取余的关系
- 最后推导出通用公式
在教学时可以先用循环写法,再优化为公式解法,让学生体会算法优化的过程。
