【UVA - 11636】Hello World!
真的是 Hello World
题目描述
当你第一次让计算机打印出 "Hello World!"这句话时,你感到非常高兴,不知道编程和算法的世界会变得多么复杂和有趣。
那时你对循环一无所知,所以要打印7行 “Hello World!”,你只需要 复制和粘贴几行。
如果你足够聪明,你可以编写一段代码来打印 “Hello World! 世界!” 7次的代码,只需使用3个粘贴命令。
请注意,我们并不关心 所需的复制命令的数量。
一个打印 "Hello World!"的简单程序如图1所示。
通过 通过复制单个打印语句并粘贴,我们得到一个打印两行 "Hello World!"的程序。然后复制这两条打印语句并粘贴,我们得到一个打印出四行 "Hello World!"的程序。然后复制这四个语句中的三个并粘贴,我们可以得到一个 程序,可以打印出7行 “Hello World!”(图4)。
所以总共需要三个粘贴命令 当然,粘贴后不允许删除任何一行。
鉴于你需要打印的 "Hello 世界!"的行数,你必须找出所需的最少粘贴次数。图1所示的源程序,找出制作该程序所需的最少粘贴次数。
输入:
每组数据一个数n(n<=1e8)
多组测试数据以n<0结束输入
输出:
输出Case i:最少操作次数
输入样例
2
5
-1
输入样例
Case 1: 1
Case 2: 3
分析
这道题目一定是一道贪心算法的题目。
因为作者使用了 AI 提前剧透 因为这道题目的 nnn 的范围达到了 100001000010000,应该就是贪心了。
思路
首先既然是贪心,我们要考虑最多的次数。
每次都把上一次的所有的 可以复制到的 全部复制了
第一次是 202^020 第二次是 212^121 第 nnn 次是 2n−12^{n-1}2n−1
全部相加得:2n−12^n-12n−1
简单证明一下:
20+21+22+...+2n−1=2n2^0+2^1+2^2+...+2^{n-1}=2^n20+21+22+...+2n−1=2n
设 S=20+21+22+...+2n−1S=2^0+2^1+2^2+...+2^{n-1}S=20+21+22+...+2n−1
那么 2S=2(20+21+22+...+2n−1)=21+22+23+...+2n2S = 2(2^0+2^1+2^2+...+2^{n-1})=2^1+2^2+2^3+...+2^n2S=2(20+21+22+...+2n−1)=21+22+23+...+2n
两式相减得 2S−S=(21+22+23+...+2n)−(20+21+22+...+2n−1)2S-S=(2^1+2^2+2^3+...+2^n)-(2^0+2^1+2^2+...+2^{n-1})2S−S=(21+22+23+...+2n)−(20+21+22+...+2n−1)
最后 S=2n−20=2n−1S=2^n-2^0=2^n-1S=2n−20=2n−1
证毕
代码真是太短了
#include <cstdio>
#include <cmath>signed main() {int n, count=1;while(scanf("%d", &n) == 1 && n >= 0) {printf("Case %d: %d\n",count,(int) ceil(log2(n)));count++;}return 0;
}
时间复杂度分析 & 坑点
log2
函数的时间复杂度在最差的情况为 O(logn)O(\log n)O(logn)
所以这个代码的时间复杂度为 O(klogn)O(k \log n)O(klogn) kkk 是测试数据的个数
注意上面代码的 n >= 0
因为有的数据的结尾不是 -1
而是别的负数