1. 题目解析与需求理解
题目要求我们判断给定的正整数a是否存在一个正整数b,使得a等于b的四次方(即a = b⁴)。换句话说,我们需要找到一个整数b,使得b的四次方等于a。
输入格式:
- 第一行是一个正整数t,表示测试数据的组数
- 接下来t行,每行一个正整数a
输出格式:
- 对于每个a,如果存在满足条件的b,输出b;否则输出-1
示例:
- 输入16,输出2(因为2⁴=16)
- 输入81,输出3(因为3⁴=81)
- 输入10,输出-1(因为10不是任何整数的四次方)
2. 解题思路分析
2.1 数学原理
我们需要找到一个整数b,使得b⁴ = a。这相当于:
- 先对a开平方,得到b²
- 再对b²开平方,得到b
因此,可以分两步计算:
- 计算a的平方根,得到中间值temp = sqrt(a)
- 再计算temp的平方根,得到b = sqrt(temp)
- 最后验证b⁴是否等于a
2.2 算法选择
直接遍历所有可能的b值(从1到sqrt(sqrt(a)))并检查b⁴是否等于a是可行的,但对于大的a值(如1e8),这会比较耗时。更高效的方法是:
- 计算b = floor(sqrt(sqrt(a)))(即对a开四次方后取整)
- 检查b⁴是否等于a
- 如果等于,输出b;否则输出-1
这种方法利用了数学运算的精确性,避免了不必要的循环。
2.3 边界条件
需要考虑的特殊情况:
- a=1时,b=1(1⁴=1)
- a=0时(虽然题目说a是正整数,但理论上0的任何正整数次方都是0)
- 大数情况(如a=1e8,b=100,因为100⁴=1e8)
3. 代码实现详解
3.1 基本框架
#include <iostream> #include <cmath> // 用于sqrt函数 using namespace std; int main() { int t; cin >> t; while (t--) { int a; cin >> a; // 计算b // 检查条件 // 输出结果 } return 0; }3.2 计算b值
计算b的关键步骤:
- 计算a的平方根:
double temp = sqrt(a) - 计算temp的平方根:
int b = sqrt(temp) - 检查b⁴是否等于a
优化:可以直接计算四次方根,因为sqrt(sqrt(a)) = a^(1/4)
int b = sqrt(sqrt(a));3.3 验证条件
由于浮点数运算可能有精度问题,我们需要验证:
- b⁴ == a
- (b+1)⁴ == a(处理四舍五入的情况)
但通常对于整数a,直接计算b = floor(a^(1/4))然后验证b⁴是否等于a即可。
3.4 完整代码
#include <iostream> #include <cmath> using namespace std; int findB(int a) { int b = sqrt(sqrt(a)); // 等价于a^(1/4)取整 if (b * b * b * b == a) { return b; } else { return -1; } } int main() { int t; cin >> t; while (t--) { int a; cin >> a; cout << findB(a) << endl; } return 0; }4. 测试用例验证
4.1 普通测试用例
| 输入a | 预期输出b | 说明 |
|---|---|---|
| 16 | 2 | 2⁴=16 |
| 81 | 3 | 3⁴=81 |
| 10 | -1 | 无解 |
| 1 | 1 | 1⁴=1 |
| 625 | 5 | 5⁴=625 |
4.2 边界测试用例
| 输入a | 预期输出b | 说明 |
|---|---|---|
| 0 | -1 | 题目说a是正整数,但考虑边界 |
| 256 | 4 | 4⁴=256 |
| 100000000 | 100 | 100⁴=1e8 |
| 43046721 | 81 | 81⁴=43046721 |
4.3 错误处理
- 输入非正整数(题目保证输入是正整数,可不处理)
- 极大值(如1e8,应正确处理)
5. 复杂度分析
- 时间复杂度:O(t),因为每个测试用例的处理时间是O(1)
- 空间复杂度:O(1),只用了常数空间
6. 优化与扩展
6.1 优化思路
- 使用位运算代替乘法和开方(但现代编译器会自动优化)
- 预计算所有可能的b值(对于a≤1e8,b≤100),但空间换时间不一定值得
6.2 扩展问题
- 如果a很大(如1e18),可能需要使用long long
- 如果要求输出所有满足条件的b(虽然题目保证唯一性)
7. 常见错误与调试
7.1 常见错误
- 忘记处理t=0的情况(题目保证t≥1)
- 浮点数精度问题(如直接比较pow(b,4)==a可能不精确)
- 整数溢出(如b⁴可能超过int范围,但题目中a≤1e8,b≤100,不会溢出)
7.2 调试技巧
- 打印中间值(如b和b⁴)
- 使用assert验证条件
- 测试边界值
8. 最终代码
#include <iostream> #include <cmath> using namespace std; int findB(int a) { int b = sqrt(sqrt(a)); // 计算四次方根 if (b * b * b * b == a) { return b; } // 检查b+1,处理四舍五入 if ((b + 1) * (b + 1) * (b + 1) * (b + 1) == a) { return b + 1; } return -1; } int main() { ios::sync_with_stdio(false); // 加速输入输出 cin.tie(nullptr); int t; cin >> t; while (t--) { int a; cin >> a; cout << findB(a) << '\n'; // 用'\n'比endl更快 } return 0; }9. 总结
本题考察了数学运算和条件判断的基本能力。关键点在于:
- 理解四次方与平方根的关系
- 正确处理整数运算和边界条件
- 编写高效且正确的代码
通过这个问题,我们巩固了:
- 数学运算的应用
- 循环和条件判断的使用
- 边界条件的处理
- 代码优化技巧