2025年6月GESP(C++二级): 幂和数
2025年6月GESP(C++二级): 幂和数
题目描述
对于正整数 nnn,如果 nnn 可以表为两个 222 的次幂之和,即 n=2x+2yn = 2^x + 2^yn=2x+2y(x,yx, yx,y 均为非负整数),那么称 nnn 为幂和数。
给定正整数 l,rl, rl,r,请你求出满足 l≤n≤rl \leq n \leq rl≤n≤r 的整数 nnn 中有多少个幂和数。
输入格式
一行,两个正整数 l,rl, rl,r,含义如上。
输出格式
输出一行,一个整数,表示 l,rl, rl,r 之间幂和数的数量。
输入输出样例 #1
输入 #1
2 8
输出 #1
6
输入输出样例 #2
输入 #2
10 100
输出 #2
20
说明/提示
对于所有测试点,保证 1≤l≤r≤1041 \leq l \leq r \leq 10^41≤l≤r≤104。
AC代码:
#include<bits/stdc++.h>
using namespace std; int l, r, cnt = 0; // 定义区间左右端点 l, r 和计数器 cnt
// 预计算2的幂次:2^0到2^13(因为2^14=16384>10000,所以14个元素足够覆盖题目范围)
int a[14] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192};// 检查x是否是幂和数:是否存在两个2的幂次之和等于x
bool check(int x) {// 双重循环遍历所有2的幂组合(包括相同元素)for (int i = 0; i < 14; i++) {for (int j = 0; j < 14; j++) {// 如果找到两个幂次之和等于x,返回trueif (a[i] + a[j] == x) {return true;}}}return false; // 未找到匹配组合
}int main() { cin >> l >> r; // 输入区间// 遍历区间内每个数for (int i = l; i <= r; i++) {if (check(i)) { // 检查当前数是否为幂和数cnt++; // 如果是,计数器加1}}cout << cnt; // 输出幂和数的总数return 0;
}
功能分析:
-
预计算2的幂次:
- 数组
a
存储了从 202^020 到 2132^{13}213(即1到8192)的所有2的幂次值。选择13次方是因为 214=163842^{14}=16384214=16384 已超过题目上限 10410^4104。
- 数组
-
幂和数检测(check函数):
- 通过双重循环遍历所有可能的2的幂次组合(包括相同幂次,如 2x+2x2^x + 2^x2x+2x)。
- 对每个输入数值
x
,检查是否存在一对索引(i, j)
使得 a[i]+a[j]=xa[i] + a[j] = xa[i]+a[j]=x。 - 若存在则返回
true
,否则返回false
。
-
区间统计(main函数):
- 读取区间
[l, r]
。 - 遍历区间内每个整数,使用
check
函数判断是否为幂和数。 - 统计满足条件的整数数量并输出结果。
- 读取区间
时间复杂度:
- 检测单个数值:O(142)=O(196)O(14^2) = O(196)O(142)=O(196) 次运算。
- 区间扫描:最多 10410^4104 个数(当区间为 [1,10000][1, 10000][1,10000] 时)。
- 总复杂度:O(196×104)≈O(2×106)O(196 \times 10^4) \approx O(2 \times 10^6)O(196×104)≈O(2×106),在题目约束下高效可行。
注意事项:
- 包含相同幂次:双重循环允许 i=ji = ji=j(如 2=1+12 = 1 + 12=1+1),符合题目要求。
- 幂次范围:预计算的14个幂次覆盖了 [1,16384][1, 16384][1,16384],而题目 r≤104r \leq 10^4r≤104,确保不会漏解。
文末彩蛋:
点击查看老师的个人主页,学习csp信奥赛完整系列课程:
https://edu.csdn.net/lecturer/7901