幂和数:正向枚举与集合去重
给定正整数区间 [l, r],要求统计该区间内有多少个可以表示为两个 2 的非负整数次幂之和的整数(即幂和数)。
题库1分钟阅读
对于正整数 ,如果 可以表为两个 的次幂之和,即 ( 均为非负整数),那么称 为幂和数。
给定正整数 ,请你求出满足 的整数 中有多少个幂和数。
输入格式
一行,两个正整数 ,含义如上。
输出格式
输出一行,一个整数,表示 之间幂和数的数量。
样例
输入样例 1
2 8输出样例 1
6输入样例 2
10 100输出样例 2
20数据范围
对于所有测试点,保证 。
这道题要求我们在区间 内找出所有能够表示为两个 2 的非负整数次幂之和的数(即 ,)。
结合数据范围(),我们可以发现问题规模非常小,完全可以用枚举 + 预处理的方法轻松解决。
因为 且 ,所以 和 的取值范围只需要从 枚举到 即可。
- 使用双重循环分别枚举 和 ()。
- 计算 。
- 考虑到 和 是等价的,且不同的 组合可能会算出相同的 (例如 与 ),我们需要去重。
- 可以使用
std::set或一个标记数组bool vis[20005]来记录哪些数是幂和数。
遍历区间 中的每一个整数 ,如果 是幂和数,答案计数器 ans 加 1。
#include <iostream>#include <set>
using namespace std;
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
int l, r; if (!(cin >> l >> r)) return 0;
// 用 set 存储所有不重复的幂和数 set<int> st;
// 枚举 x 和 y (2^14 = 16384,已覆盖 10^4) for (int x = 0; x <= 14; ++x) { for (int y = 0; y <= 14; ++y) { int val = (1 << x) + (1 << y); st.insert(val); } }
// 统计在 [l, r] 范围内的个数 int ans = 0; for (int i = l; i <= r; ++i) { if (st.count(i)) { ans++; } }
cout << ans << "\n";
return 0;}- 时间复杂度:
- 生成幂和数:双重循环次数为 次,每次插入
set的时间为 ,耗时极短(微秒级)。 - 统计答案:循环 次,每次在
set中查找时间复杂度为 。 - 总体时间复杂度:,远低于 1 秒限制。
- 生成幂和数:双重循环次数为 次,每次插入
- 空间复杂度:
set中最多存入 100 多个不重复的数,空间复杂度为 。