2 条题解

  • 0
    @ 2026-1-29 12:02:32

    🎯 题目理解

    一个正整数 n n 幂和数,当且仅当它可以表示为两个 2 的次幂之和:

    $$n = 2^x + 2^y \quad (x, y \geq 0,\ x \leq y\ \text{可避免重复})$$

    注意:x x y y 可以相等(比如 22+22=8 2^2 + 2^2 = 8 )。

    我们需要统计在区间 [l,r][l, r] 中有多少个这样的数。


    解题思路

    1. 枚举每个 n[l,r] n \in [l, r]
    2. 对每个 n n ,判断它是否可以写成 2x+2y 2^x + 2^y
    3. 枚举 x x y y ,计算 2x+2y 2^x + 2^y 是否等于 n n

    但注意:由于 n104 n \leq 10^4 ,而 214=16384>104 2^{14} = 16384 > 10^4 ,所以 x,y13 x, y \leq 13 即可。

    我们可以预处理所有可能的 2x 2^x 值(最多到 213 2^{13} ),然后枚举 xy x \leq y ,看 2x+2y 2^x + 2^y 是否在 [l,r][l, r] 范围内,并用集合或布尔数组记录哪些数是幂和数。

    但这里题目给出的是一个嵌套循环结构,所以我们按照这个结构填空。


    补全代码

    for (int n = l; n <= r; n++) { // 枚举 l~r 的每一个数
        bool flag = false;
        for (int x = 0; x <= 13; x++) { // 枚举 x
            int px = 1 << x; // 计算 2 的 x 次方
            for (int y = x; y <= 13; y++) { // 枚举 y,从 x 开始避免重复
                int py = 1 << y; // 计算 2 的 y 次方
                if (px + py == n) // 判断是否是幂和数
                    flag = true;
            }
        }
        if (flag) ans++; // 更新答案
    }
    

    完整代码示例

    #include <iostream>
    using namespace std;
    
    int main() {
        int l, r;
        cin >> l >> r;
        
        int ans = 0;
        for (int n = l; n <= r; n++) { // 枚举 l~r 的每一个数
            bool flag = false;
            for (int x = 0; x <= 13; x++) { // 枚举 x
                int px = 1 << x; // 计算 2 的 x 次方
                for (int y = x; y <= 13; y++) { // 枚举 y
                    int py = 1 << y; // 计算 2 的 y 次方
                    if (px + py == n) // 判断是否是幂和数
                        flag = true;
                }
            }
            if (flag) ans++; // 更新答案
        }
        cout << ans << endl;
        return 0;
    }
    

    说明

    • 1 << x 是快速计算 2x 2^x 的方式。
    • yx 开始,避免重复计算如 21+22 2^1+2^2 22+21 2^2+2^1 ,但因为加法交换律,我们只需考虑 xy x \leq y
    • 最大需要 213=8192 2^{13} = 8192 ,而 214=16384>104 2^{14} = 16384 > 10^4 ,所以 x,y13 x, y \leq 13 足够。

    样例验证

    输入 2 8

    幂和数有:

    • 20+21=1+2=3 2^0 + 2^1 = 1+2 = 3
    • 20+22=1+4=5 2^0 + 2^2 = 1+4 = 5
    • 21+21=2+2=4 2^1 + 2^1 = 2+2 = 4
    • 20+23=1+8=9>8 2^0 + 2^3 = 1+8 = 9 > 8 不行
    • 21+22=2+4=6 2^1 + 2^2 = 2+4 = 6
    • 22+22=4+4=8 2^2 + 2^2 = 4+4 = 8
    • 20+20=1+1=2 2^0 + 2^0 = 1+1 = 2

    所以 2,3,4,5,6,8 2, 3, 4, 5, 6, 8 —— 共 6 个 ✅


    最终填空答案

    for (int n = l; n <= r; n++) { // 枚举 l~r 的每一个数
        bool flag = false;
        for (int x = 0; x <= 13; x++) { // 枚举 x
            int px = 1 << x; // 计算 2 的 x 次方
            for (int y = x; y <= 13; y++) { // 枚举 y
                int py = 1 << y; // 计算 2 的 y 次方
                if (px + py == n) // 判断是否是幂和数
                    flag = true;
            }
        }
        if (flag) ans++; // 更新答案
    }
    

    ✅ 完整、正确、高效。

    信息

    ID
    484
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    7
    已通过
    2
    上传者