1 条题解
-
0
一、题目含义
给定区间 和整数 ( 是 2 的非负整数次幂,即 ),统计满足 且 是 的倍数的二元组 数量。
关键转化:因为 ,条件" 是 的倍数"等价于" 的 位以下全为 0",也就等价于 和 的 位以下完全相同,即 i%k==j%k。
于是问题变成:把区间 中的数按模 的余数分组,同一组内任取两个都满足。
二、核心做题思路
观察一个重要事实:连续的 个整数,模 的余数恰好是 各出现一次。
设区间长度 。把 从 开始,每 个分为一块:
- 完整的块数:,即每块包含 个数,余数 各一次;
- 最后剩余不满一块的数: 个,它们对应 个互不相同的余数,每个余数在这段里再额外出现 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
信息
- ID
- 1242
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 20
- 已通过
- 4
- 上传者