E01003: Hangover
math, http://cs101.openjudge.cn/pctbook/E01003/
How far can you make a stack of cards overhang a table? If you have one card, you can create a maximum overhang of half a card length. (We're assuming that the cards must be perpendicular to the table.) With two cards you can make the top card overhang the bottom one by half a card length, and the bottom one overhang the table by a third of a card length, for a total maximum overhang of 1/2 + 1/3 = 5/6 card lengths. In general you can make n cards overhang by 1/2 +1/3 + 1/4 + ... + 1/(n + 1) card lengths, where the top card overhangs the second by 1/2, the second overhangs tha third by 1/3, the third overhangs the fourth by 1/4, etc., and the bottom card overhangs the table by 1/(n + 1). This is illustrated in the figure below.

输入
The input consists of one or more test cases, followed by a line containing the number 0.00 that signals the end of the input. Each test case is a single line containing a positive floating-point number c whose value is at least 0.01 and at most 5.20; c will contain exactly three digits.
输出
For each test case, output the minimum number of cards necessary to achieve an overhang of at least c card lengths. Use the exact output format shown in the examples.
样例输入
1.00
3.71
0.04
5.19
0.00样例输出
3 card(s)
61 card(s)
1 card(s)
273 card(s)来源
Mid-Central USA 2001
这个问题要求我们找到最少的卡片数,使得它们的叠加悬空距离至少为给定的 c 值。
思路分析:
每增加一张卡片,叠加的总过hang值是一个调和数列的部分和:
- 第 1 张卡片过hang
1/2长度。 - 第 2 张卡片过hang
1/3长度。 - 第 3 张卡片过hang
1/4长度。 - 依此类推。
所以,当卡片数量为 n 时,叠加的总过hang值为:
Hn=1/2+1/3+1/4+⋯+1/n+1
我们需要找到最小的 n,使得:
Hn ≥ c
这就变成了一个计算调和数列部分和的问题。
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double c;
while (cin >> c) {
if (c == 0.00) {
break;
}
double overhang = 0.0;
int cards = 0;
// 增加卡片,直到总过hang值大于等于c
while (overhang < c) {
cards++;
overhang += 1.0 / (cards + 1); // 每张卡片的过hang值
}
// 输出结果,卡片数量
cout << cards << " card(s)" << endl;
}
return 0;
}
<iomanip>是 C++ 标准库中的一个头文件,主要用于处理输入输出的格式化。它提供了一些控制输入输出格式的工具,例如设置数字的精度、宽度、对齐方式等。常见的
iomanip功能:
设置输出的精度(
setprecision):setprecision用来指定浮点数输出的精度,即输出小数点后保留的位数。cpp#include <iostream> #include <iomanip> using namespace std; int main() { double pi = 3.14159265358979; cout << setprecision(5) << pi << endl; // 输出 3.1416 return 0; }这个例子中,
setprecision(5)设置了输出精度为 5 位数字。固定小数点输出(
fixed): 默认情况下,C++ 会根据数字的大小自动决定浮点数是以科学计数法(例如1.23e+4)还是普通的十进制形式输出。如果你希望强制浮点数以小数点形式输出,可以使用fixed。cpp#include <iostream> #include <iomanip> using namespace std; int main() { double pi = 3.14159265358979; cout << fixed << setprecision(4) << pi << endl; // 输出 3.1416 return 0; }这段代码会强制
pi以小数点形式输出,保留 4 位小数。设置输出宽度(
setw):setw用来设置输出字段的宽度。如果输出的数据宽度小于setw设置的宽度,C++ 会自动填充空格来补齐。cpp#include <iostream> #include <iomanip> using namespace std; int main() { int x = 42; cout << setw(5) << x << endl; // 输出 " 42"(宽度为5) return 0; }对齐设置(
left,right,internal): 通过left,right, 和internal来控制输出对齐方式:
left:左对齐right:右对齐(默认)internal:将符号位(正负号)对齐到输出字段的内部(即数字右侧,符号前)cpp#include <iostream> #include <iomanip> using namespace std; int main() { cout << left << setw(10) << "Hello" << endl; // 输出 "Hello " cout << right << setw(10) << "Hello" << endl; // 输出 " Hello" return 0; }填充字符(
setfill):setfill用于设置输出时填充字符。如果字段宽度不足,输出会使用该字符来填充。cpp#include <iostream> #include <iomanip> using namespace std; int main() { cout << setfill('*') << setw(10) << 42 << endl; // 输出 "******42" return 0; }常见的
iomanip常量:
fixed:强制以小数点形式输出浮点数。scientific:强制以科学计数法输出浮点数。setprecision(n):设置浮点数输出的精度,保留 n 位小数。setw(n):设置输出的宽度,输出内容小于 n 时会自动填充空格。setfill(ch):设置填充字符,输出内容小于指定宽度时会用该字符填充。示例代码:
cpp#include <iostream> #include <iomanip> using namespace std; int main() { double pi = 3.14159265358979; int number = 42; // 设置精度为 3 位小数 cout << fixed << setprecision(3) << pi << endl; // 输出 3.142 // 设置输出宽度为 10,使用填充字符 '*' cout << setfill('*') << setw(10) << number << endl; // 输出 "******42" // 设置对齐方式为右对齐 cout << right << setw(10) << number << endl; // 输出 " 42" return 0; }总结:
<iomanip>使得你可以灵活地控制 C++ 输出格式,常用的有设置浮点数精度、输出宽度、对齐方式、填充字符等功能。