题解:洛谷 P5720 一尺之棰
【题目来源】
【题目描述】
《庄子》中说到,“一尺之棰,日取其半,万世不竭”。第一天有一根长度为 \(a\) 的木棍,从第二天开始,每天都要将这根木棍锯掉一半(每次除 \(2\),向下取整)。第几天的时候木棍的长度会变为 \(1\)?
【输入】
输入一个正整数 \(a\),表示木棍长度。
【输出】
输出一个正整数,表示要第几天的时候木棍长度会变为 \(1\)。
【输入样例】
100
【输出样例】
7
【核心思想】
-
问题分析:给定初始木棍长度 \(a\),每天将其锯掉一半(整数除法,向下取整),求第几天长度变为 \(1\)。这是一个模拟折半过程的问题。
-
算法选择:
- 循环折半模拟:每天执行 \(a = a / 2\)(整数除法),同时天数计数器累加,直到 \(a = 1\)
-
关键步骤:
- 读入数据:
cin >> a - 初始化:
day = 1(第一天已有长度 \(a\)) - 循环折半(当
a != 1):a /= 2:长度减半(整数除法自动向下取整)day++:天数加 1
- 输出结果:
day
- 读入数据:
-
时间/空间复杂度:
- 时间复杂度:\(O(\log a)\),每次循环 \(a\) 减半,最多循环 \(\log_2 a\) 次
- 空间复杂度:\(O(1)\),仅需两个变量
-
折半模拟的核心思想:
- 整数除法特性:C++ 中
a /= 2对整数自动向下取整,恰好符合"锯掉一半"的要求 - 天数计数:从第 1 天开始计数,每次折半后进入下一天,确保最终天数包含达到 1 的那一天
- 对数级效率:\(a\) 每次减半,循环次数与 \(a\) 的大小成对数关系,效率极高
- 适用于折半递推、对数级模拟、过程追踪类入门问题
- 整数除法特性:C++ 中
【算法标签】
入门 #模拟
【代码详解】
#include <bits/stdc++.h> // 包含标准库头文件(万能头文件)
using namespace std; // 使用标准命名空间
/**
* 主函数 - 程序入口
* @return 程序执行状态码(0表示成功)
*/
int main()
{
int a; // 定义变量:初始a
int day = 1; // 定义变量:天数计数器,初始为1
cin >> a; // 输入初始
// 模拟细胞分裂过程(每天数量减半)
while (a != 1) // 当数量不为1时继续循环
{
a /= 2; // 数量减半(整数除法)
day++; // 天数加1
}
cout << day; // 输出总天数
return 0; // 程序正常结束
}
【运行结果】
100
7
浙公网安备 33010602011771号