1 条题解

  • 0
    @ 2026-6-19 10:31:07

    📝 题目大意

    给定整数 NN,求所有满足 N=a×2b+cN = a \times 2^b + c 的非负整数三元组 (a,b,c)(a, b, c) 中,a+b+ca + b + c 的最小值。

    💡 解题思路

    1. 题目分析N1018N \leq 10^{18}a,b,ca, b, c 均为非负整数。直接枚举三元组不可能,但 bb 的范围很小——2b2^b 指数增长,当 2b>N2^b > Naa 只能为 00,此时 a+b+c=N+bNa+b+c = N + b \geq N,而 b=0b=0 时取 (a=N,c=0)(a=N, c=0) 已经得到 a+b+c=Na+b+c = N。因此 bb 只需枚举 00log2N\lfloor\log_2 N\rfloor,约 6060 个值,完全可以暴力。

    2. 算法推导

      • 固定 bb 时的最优策略:对于给定的 bb,我们需要最小化 a+ca + c(因为 bb 固定)。由 N=a×2b+cN = a \times 2^b + c 可得 c=Na×2bc = N - a \times 2^b,因此 a+c=Na×(2b1)a + c = N - a \times (2^b - 1)
      • 因为 2b102^b - 1 \geq 0b=0b=0 时等于 00b1b \geq 1 时大于 00),a+ca + c 关于 aa 单调不增——aa 越大,a+ca + c 越小(或不变)。
      • 同时 c0c \geq 0 要求 a×2bNa \times 2^b \leq N,即 aN/2ba \leq \lfloor N / 2^b \rfloor。所以 aa 的最大可行值就是 a=N/2ba = N / 2^b(整除),此时 c=Nmod2bc = N \bmod 2^b
      • 因此对于每个 bb,最优三元组为 (a=N/2b, b, c=Nmod2b)(a = N / 2^b,\ b,\ c = N \bmod 2^b),对应的目标值为 N/2b+b+Nmod2bN / 2^b + b + N \bmod 2^b
      • 枚举所有 bb 使得 2bN2^b \leq N,取最小值即可。代码中 mul 维护 2b2^bb00 递增,每次 ans = min(ans, n / mul + b + n % mul)
    3. 边界与细节

      • b=0b=0 的情况20=12^0 = 1,此时 a=Na = Nc=0c = 0a+b+c=Na+b+c = N。这是所有解的上界。
      • N=1N=1b=0b=0a=1,c=0a=1, c=0,答案为 11b=1b=121=2>12^1=2 > 1,循环退出。
      • 溢出N1018N \leq 10^{18},答案在 long long 范围内,无需取模。初始 ans 设为 9e18(大于 101810^{18})足够安全。
      • 循环终止条件while (mul <= n)2b>N2^b > N 时退出。此时若继续枚举,a=0,c=Na=0, c=N,目标值为 N+bNN + b \geq N,不会优于 b=0b=0 时的答案 NN,因此提前终止是正确的。

    ⏱️ 复杂度分析

    • 时间复杂度bb00 枚举到 log2N\lfloor\log_2 N\rfloor,共 O(logN)O(\log N) 次迭代,每次 O(1)O(1) 运算,总复杂度 O(logN)O(\log N)
    • 空间复杂度:仅使用常数个变量,O(1)O(1)

    💻 标准代码 (C++)

    #include <bits/stdc++.h>
    using namespace std;
    
    long long n, a, b, c, ans = 9e18; // ans 初始化为极大值(9e18 > 10^18)
    
    int main(){
        cin >> n;
        long long mul = 1; // mul = 2^b
        while (mul <= n){  // 当 2^b > N 时,a 只能为 0,不会更优
            // 固定 b 时,最优的 a = n / mul, c = n % mul
            ans = min(ans, n / mul + b + n % mul);
            b++;          // 指数加 1
            mul *= 2;     // mul = 2^{b}
        }
        cout << ans << '\n';
        return 0;
    }
    
    • 1

    信息

    ID
    865
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者