题目题解:猴子吃桃
题意分析
一共有
n
个桃子;
第 1 天猴子需要吃掉
m
个桃子才能吃饱;
第 2 天要吃
m+1
个;
第 3 天吃
m+2
个,往后每一天比前一天多吃 1 个;
求出猴子能够连续吃饱多少天,也就是吃到剩下桃子不够当天食量为止。
核心思路(对应代码逻辑)
变量
i
代表当天猴子需要吃的桃子数量,初始
i=m
;
for 循环条件:只要剩余桃子
n≥i
,猴子这天可以吃饱,就把当天吃掉的桃子从总数减去(n = n - i),然后
i
自增 1;
当循环结束时,
i
是下一天猴子想吃的数量;总共吃饱的天数 =
i−m
。
样例推演(输入
n=5, m=2
)
初始:
i=2, n=5
5≥2
:
n=5−2=3
,
i=3
(第 1 天吃饱)
i=3, n=3
3≥3
:
n=3−3=0
,
i=4
(第 2 天吃饱)
i=4, n=0
:
0<4
,循环终止;
天数:
i−m=4−2=2
,输出2,和样例匹配。
代码逐行解读
cpp
运行
for(i=m;n>=i;i++) n -= i;
初始化:i = m;
循环条件:n >= i:剩余桃子足够今天吃;
每次循环内部:n = n-i,减去当天吃掉桃子,然后执行i++,下一天食量 + 1;
循环结束之后:
cout << i - m;:总共吃饱的天数。
两种等价写法
写法 1 while 循环(逻辑更直白)
cpp
运行
int cnt = 0;
int i = m;
while(n >= i)
{
n -= i;
cnt ++;
i ++;
}
cout << cnt;
写法 2 数学公式解法(不用循环)
设一共吃
x
天,吃掉桃子总和:
m+(m+1)+(m+2)+⋯+(m+x−1)≤n
等差数列求和:
x⋅m+
2
x(x−1)
≤n
枚举
x
的最大值即可,
n≤100
,循环写法完全够用。
边界测试举例
输入:
n=2, m=2
:
n=2
够吃一天,之后
i=3
不够,答案是
1
;
输入:
n=3, m=2
:第一天吃掉 2 剩 1,第二天需要 3 个不够,答案是
1
。
代码优点
代码极其精简,利用 for 循环把变量初始化、条件判断、自增写在一行;
数据范围很小
n≤100
,时间复杂度完全没问题;
不用额外定义天数变量,用
i−m
巧妙算出答案。
只要题解,不要代码
题解
题意理解
总共有
n
个桃子,猴子第 1 天要吃
m
个桃子,之后每一天需要吃的桃子数量比前一天多 1 个。计算猴子一共可以吃饱的天数,当剩余桃子的数量小于当天需要吃的数量时停止。
解题思路
设定当天所需桃子数量初始值为
m
;
判断剩余桃子是否足够当天食用:
如果桃子数量大于等于当天要吃的数量,就把当天吃掉的桃子从总数减去,下一天的食量再加 1;
如果桃子不够当天食用,结束循环;
天数计算:结束循环时,用现在的食量减去初始食量
m
,得到总共吃饱的天数。
样例推导(
n=5,m=2
)
第一天:需要吃 2 个,桃子足够,剩余桃子
5−2=3
,次日需要吃 3 个;
第二天:需要吃 3 个,桃子足够,剩余桃子
3−3=0
,次日需要吃 4 个;
第三天:只剩 0 个桃子,小于 4 个,不能吃饱;
一共吃饱天数:
4−2=2
。
数学原理
猴子每天吃的桃子数量构成等差数列:
m, m+1, m+2…
。
设吃饱天数为
x
,前
x
天吃掉桃子总和:
S=m+(m+1)+(m+2)+⋯+(m+x−1)=x×m+
2
x(x−1)
找到满足
S≤n
的最大整数
x
,这个
x
就是答案。
关键点总结
循环条件核心:剩余桃子 ≥ 当天要吃的桃子;
结束循环后的食量减去初始食量就是答案,不需要额外计数器;
数据范围很小,循环模拟是最简单稳妥的方法。