1 条题解

  • 0
    @ 2026-10-18 19:56:35

    一、题目含义

    给定区间 [l,r][l,r] 和整数 kk(kk 是 2 的非负整数次幂,即 k=2tk=2^t),统计满足 l≤i<j≤rl\le i<j\le r 且 i⊕ji\oplus j 是 kk 的倍数的二元组 (i,j)(i,j) 数量。

    关键转化:因为 k=2tk=2^t,条件"i⊕ji\oplus j 是 kk 的倍数"等价于"i⊕ji\oplus j 的 tt 位以下全为 0",也就等价于 ii 和 jj 的tt 位以下完全相同,即 i%k==j%k。

    于是问题变成:把区间 [l,r][l,r] 中的数按模 kk 的余数分组,同一组内任取两个都满足。


    二、核心做题思路

    观察一个重要事实:连续的 kk 个整数,模 kk 的余数恰好是 0,1,…,k−10,1,\dots,k-1 各出现一次。

    设区间长度 w=r−l+1w = r-l+1。把 [l,r][l,r] 从 ll 开始,每 kk 个分为一块:

    • 完整的块数:d1=⌊w/k⌋d_1 = \lfloor w/k\rfloor,即每块包含 kk 个数,余数 0∼k−10\sim k-1 各一次;
    • 最后剩余不满一块的数:d2=w mod kd_2 = w \bmod k 个,它们对应 d2d_2 个互不相同的余数,每个余数在这段里再额外出现 1 次。

    因此对每个余数类,其计数 cvc_v 只有两种可能:

    • 有 k−d2k-d_2 个余数,它们只出现在完整块中,计数为 d1d_1;
    • 有 d2d_2 个余数,它们出现在所有完整块中且在末尾残缺段再出现一次,计数为 d1+1d_1+1。

    答案即:

    $$\text{ans} = (k-d_2)\cdot\frac{d_1(d_1-1)}{2} + d_2\cdot\frac{d_1(d_1+1)}{2} $$

    三、C 语言代码

    #include <stdio.h>
    
    int main() {
        long long l, r, k;
        scanf("%lld %lld %lld", &l, &r, &k);
    
        long long w  = r - l + 1;      // 区间长度
        long long d1 = w / k;          // 完整块数(每块含 k 个数,余数 0..k-1 各一次)
        long long d2 = w % k;          // 末尾残缺段长度(对应 d2 个互不相同的余数,各多出现一次)
    
        // 有 k-d2 个余数出现 d1 次,有 d2 个余数出现 d1+1 次
        long long ans = (k - d2) * d1 * (d1 - 1) / 2 + d2 * d1 * (d1 + 1) / 2;
    
        printf("%lld\n", ans);
        return 0;
    }
    

    代码说明

    1. 读入 l,r,kl,r,k,算出区间长度 ww;
    2. d1=w/kd_1=w/k 是完整块数,d2=w%kd_2=w\%k 是残缺段长度;
    3. 输出答案。
    • 1

    信息

    ID
    1242
    时间
    1000ms
    内存
    256MiB
    难度
    9
    标签
    递交数
    20
    已通过
    4
    上传者