1 条题解

  • 0
    @ 2026-4-3 13:51:14

    灯泡开关问题 详细题解

    问题核心转化

    有编号为 1,2,3,1,2,3,\dots 的无限个灯泡,初始状态均为关闭。 第 11 轮:切换所有 11 的倍数的灯泡; 第 22 轮:切换所有 22 的倍数的灯泡; 第 ii 轮:切换所有 ii 的倍数的灯泡; 无限轮操作后,求kk 个亮着的灯泡的编号


    一、数学推导:灯泡最终状态规律

    1. 灯泡状态与约数个数的关系

    灯泡 ii 被切换的次数 = ii正约数的个数

    • 初始状态:关闭
    • 切换偶数次:最终
    • 切换奇数次:最终

    因此:

    • ii偶数个约数 \rightarrow 灯泡亮
    • ii奇数个约数 \rightarrow 灯泡灭

    2. 约数个数的奇偶性规律

    正整数的约数都是成对出现的(如 66 的约数:1×6,2×31\times6,2\times3),因此绝大多数数的约数个数为偶数。 只有完全平方数1,4,9,16,1,4,9,16,\dots)存在一个约数是自身平方根(如 4=2×24=2\times2),约数会重复,最终约数个数为奇数

    结论:

    • 非完全平方数 \rightarrow 灯泡亮
    • 完全平方数 \rightarrow 灯泡灭

    问题简化为:求第 kk 个非完全平方数


    二、核心公式推导

    设目标数为 nn,在 1n1\sim n 中:

    • 完全平方数的个数为 n\lfloor \sqrt{n} \rfloor(向下取整)
    • 非完全平方数的个数为 nnn - \lfloor \sqrt{n} \rfloor

    我们需要找到最小的 nn,满足:

    nn=kn - \lfloor \sqrt{n} \rfloor = k

    1. 二分查找解法(标程思路)

    二分查找的核心:在范围 [1,2×1018][1, 2\times10^{18}] 内寻找满足 nnkn - \lfloor \sqrt{n} \rfloor \geq k 的最小 nn

    • 左边界 l=1l=1,右边界 r=2×1018r=2\times10^{18}(覆盖极大数据范围)
    • 取中间值 midmid,计算 1mid1\sim mid 内非完全平方数的个数 midmidmid - \lfloor \sqrt{mid} \rfloor
    • 若个数 k\geq k,说明答案在左半区间,调整右边界;否则调整左边界
    • 最终 rr 即为第 kk 个非完全平方数

    2. 直接公式解法

    数学推导可得直接计算公式:

    n=k+k+0.5n = \lfloor k + \sqrt{k} + 0.5 \rfloor

    该公式可直接计算出答案,效率更高。


    三、标程代码解析

    #include <bits/stdc++.h>
    using namespace std;
    int main(){
        int t;
        cin >> t;        // 输入测试用例数
        while(t--){      // 循环处理每个测试用例
            long long k, l = 1, r = 2e18;
            cin >> k;    // 输入目标k
            // 二分查找核心逻辑
            while(r - l > 1){
                long long mid = (l + r) >> 1;  // 等价于 (l+r)/2,避免溢出
                // 计算1~mid中非完全平方数的个数,sqrtl为高精度平方根函数
                long long cnt = mid - (long long)sqrtl(mid);
                if(cnt >= k) r = mid;  // 个数足够,答案在左区间
                else l = mid;          // 个数不足,答案在右区间
            }
            cout << r << "\n";  // 输出最终答案
        }
        return 0;
    }
    

    关键细节说明

    1. 数据类型:使用 long long 避免数据溢出(kk 可极大)
    2. 高精度平方根sqrtl() 用于长整型的平方根计算,保证精度
    3. 二分边界:右边界设为 2×10182\times10^{18},覆盖所有题目可能的输入范围
    4. 循环条件r-l>1 确保最终找到唯一解 rr

    四、示例验证

    • k=1k=1:第 11 个非完全平方数是 22,公式:1+1+0.5=2\lfloor 1+\sqrt{1}+0.5 \rfloor=2
    • k=3k=3:第 33 个非完全平方数是 55,公式:3+3+0.5=5\lfloor 3+\sqrt{3}+0.5 \rfloor=5
    • k=5k=5:第 55 个非完全平方数是 77,公式:5+5+0.5=7\lfloor 5+\sqrt{5}+0.5 \rfloor=7

    验证结果完全正确。


    总结

    1. 灯泡亮灭等价于判断是否为非完全平方数
    2. 问题转化为求第 kk 个非完全平方数
    3. 核心公式:nn=k\boldsymbol{n - \lfloor \sqrt{n} \rfloor = k}
    4. 解法:二分查找(标程)/ 直接公式 $\boldsymbol{n = \lfloor k + \sqrt{k} + 0.5 \rfloor}$。
    • 1

    信息

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