题目地址:
https://www.luogu.com.cn/problem/P1150
题目描述:
Peter有
n
n
n根烟,他每吸完一根烟就把烟蒂保存起来,
k
k
k(
k
>
1
k>1
k>1)个烟蒂可以换一个新的烟,那么Peter最终能吸到多少根烟呢?吸烟有害健康。
输入格式:
每组测试数据一行包括两个整数
n
,
k
n, k
n,k(
1
<
n
,
k
≤
1
0
8
1 < n, k \le 10^8
1<n,k≤108)。
输出格式:
对于每组测试数据,输出一行包括一个整数表示最终烟的根数。
数据范围:
对于
100
%
100\%
100%的数据,
1
<
n
,
k
≤
1
0
8
1<n, k \le 10^8
1<n,k≤108。
法1:模拟。代码如下:
#include <iostream>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
int count = 0; // 统计总共的抽烟数
int end = 0; // 统计当前的烟蒂数
do {
count += n; // 先抽n根烟
end += n; // 新增n根烟蒂
n = end / k; // 换烟
end %= k; // 计算还剩下的烟蒂数
} while (n > 0); // 只要还有烟抽,就继续循环
cout << count << endl;
return 0;
}
空间复杂度 O ( 1 ) O(1) O(1),时间复杂度为 O ( log k n ) O(\log_kn) O(logkn),也就是 O ( log n ) O(\log n) O(logn)。
法2:数论。证明在后面。代码如下:
#include <iostream>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
cout << n + (n - 1) / (k - 1) << endl;
return 0;
}
时空复杂度都为 O ( 1 ) O(1) O(1)。
具体证明如下:
假设最后Peter总共抽了
x
x
x根烟,则其中
(
x
−
n
)
(x - n)
(x−n)根烟是用烟蒂换来的,所以从头到尾,Peter抽烟产生出来的烟蒂总数至少为
(
x
−
n
)
k
(x-n)k
(x−n)k,之所以是至少,是因为最后有可能剩下来一些烟蒂不够再换烟。其次,因为Peter总共抽了
x
x
x根烟,所以一共产生出
x
x
x个烟蒂,但最后抽的那根烟的烟蒂,是没有办法换成烟的,否则如果它换成了烟,就跟”最后抽的“的定义矛盾(当然如果允许借烟蒂,那么最后的烟蒂可以作归还用途,不在讨论范围之列)。(严格来说,还要证明“最后的烟蒂”的存在性。这一点在
k
>
1
k>1
k>1时是容易证明的,因为每轮换烟下来,烟蒂的数目严格减少,所以总会到某个时刻,某个烟蒂成为最后的烟蒂)。所以得出这样的不等式:
(
x
−
n
)
k
≤
x
−
1
(x-n)k\le x-1
(x−n)k≤x−1于是得到
x
≤
n
+
n
−
1
k
−
1
x\le n+\frac{n-1}{k-1}
x≤n+k−1n−1下面证明,
x
x
x可以取到
n
+
⌊
n
−
1
k
−
1
⌋
n+\lfloor\frac{n-1}{k-1}\rfloor
n+⌊k−1n−1⌋。
首先,先抽完
n
n
n根烟,产生了
n
n
n个烟蒂,然后按照每组
k
−
1
k-1
k−1个烟蒂分成
i
i
i个非空组,按数字对烟蒂编号,并设最后一组为
S
i
S_i
Si:
{
1
,
2
,
.
.
.
,
k
−
1
}
,
{
k
,
k
+
1
,
.
.
.
,
2
k
−
2
}
,
.
.
.
,
S
i
\{1,2,...,k-1\},\{k,k+1,...,2k-2\},...,S_i
{1,2,...,k−1},{k,k+1,...,2k−2},...,Si现在进行这样的操作,将烟蒂
k
k
k并入第一组,换成一根烟后抽掉,再把烟蒂还回第二组,如此这般一直操作下去,可以额外抽
i
−
1
i-1
i−1根烟。由于
S
i
S_i
Si非空,所以
i
−
1
=
⌊
n
−
1
k
−
1
⌋
i-1=\lfloor\frac{n-1}{k-1}\rfloor
i−1=⌊k−1n−1⌋,由
x
x
x的定义得到:
x
≥
n
+
⌊
n
−
1
k
−
1
⌋
x\ge n + \lfloor\frac{n-1}{k-1}\rfloor
x≥n+⌊k−1n−1⌋综上所述,
x
=
n
+
⌊
n
−
1
k
−
1
⌋
x= n + \lfloor\frac{n-1}{k-1}\rfloor
x=n+⌊k−1n−1⌋
由上面的证明容易知道,如果允许“借尸还魂”,也就是向别人借烟蒂换烟,然后再还回去,则 x = n + ⌊ n k − 1 ⌋ x= n + \lfloor\frac{n}{k-1}\rfloor x=n+⌊k−1n⌋