目录
一、问题描述
题目描述:
Peter 有 n 根烟,他每吸完一根烟就把烟蒂保存起来,k(k > 1)个烟蒂可以换一个新的烟,那么 Peter 最终能吸到多少根烟呢?
输入格式:
每组测试数据一行包括两个整数 n, k(n > 1,1 < k <= 10^8 )。
输出格式:
对于每组测试数据,输出一行包括一个整数表示最终烟的根数。
样例输入 1:
4 3
样例输出 1:
5
样例输入 2:
10 3
样例输出 2:
14
二、用迭代求解
假设 k = 3,而当前的烟蒂数为 2 时,如果允许借一个烟蒂,Peter 则可以再抽一根烟。但通过题目给出的两组数据,我们可以知道是不允许借烟蒂的。
#include <stdio.h>
int main()
{
int n = 0, k = 0;
scanf("%d%d", &n, &k);
int counts = n; // counts 统计 Peter 当前抽了多少根烟
int cigarette_butts = n; // cigarette_butts 统计当前烟蒂的个数
while (cigarette_butts / k)
{
counts += cigarette_butts / k; // 拿当前的烟蒂去换烟
cigarette_butts = cigarette_butts / k + cigarette_butts % k;
// 当前烟蒂的个数 = 新换的烟抽完后产生的烟蒂 + 之前没有拿去换烟的烟蒂
}
printf("counts = %d\n", counts);
return 0;
}
三、用数学方法求解
当 Peter 抽完 n 根烟后,产生了 n 个烟蒂,分别用数字 1 ~ n 对每个烟蒂进行编号,然后把这 n 个烟蒂按每组 k - 1 个分为 i 非空组,则有:
{1, 2, ..., k-1}, {k, k+1, ..., 2k-2}, ... ...。
现在进行这样的操作,先将编号为 k 的烟蒂并入第 1 组,然后将第 1 组的烟蒂拿去换烟,Peter 抽完后再把烟蒂还给第 2 组,依此方式一直操作下去,Peter 可以额外再抽 i - 1 根烟。由于第 i 组非空,即至少有一个烟蒂,所以 i - 1 = ⌊(n - 1) / (k - 1)⌋。
那么 Peter 最终抽了 n + ⌊(n - 1) / (k - 1)⌋ 根烟。
#include <stdio.h>
int main()
{
int n = 0, k = 0;
scanf("%d%d", &n, &k);
int counts = n + (n - 1) / (k - 1);
printf("counts = %d\n", counts);
return 0;
}
如果允许借烟蒂的话,如果 i 个非空组都是每组 k - 1 个烟蒂,则 Peter 可以额外再抽 i 根烟,因为第 i 组可以借一个烟蒂,然后把第 i 组拿去换烟,抽完后再把烟蒂还回去;如果第 i 个组没有 k - 1 个烟蒂,则 Peter 可以额外再抽 i - 1 根烟。
然而无论是哪种情况,Peter 可以额外再抽 ⌊n / (k - 1)⌋ 根烟。那么 Peter 最终就抽了 n + ⌊n / (k - 1)⌋ 根烟。