关于CF-2276C的思路和题解

题目大意

给定数组长度 n 和整数 k,统计满足两个条件的子数组数目:

  1. 子数组的和对 k 取模等于 0;
  2. 子数组长度至少为 k+1。

解题思路

核心是前缀和 + 同余性质 + 二分查找。
区间 [l,r] 的和可以用前缀和表示:sum = s [r] - s [l-1]。
若 sum mod k = 0,等价于 s[r] mod k = s[l-1] mod k。
同时要求子数组长度 ≥ k+1,转换成下标条件:r - (l-1) ≥ k+1。
也就是:找到一对下标 pos 和 r,前缀和模 k 的余数相同,并且两个下标差值大于等于 k+1。

我的实现步骤:

  1. 多组测试用例循环处理。
  2. 遍历数组,一边累加得到前缀和,一边计算前缀和模 k 的余数。
  3. 使用 map,key 存储余数,value 是 vector,保存所有拥有该余数的下标。因为顺序遍历数组,vector 里面的下标天然是升序排列。
  4. 在遍历数组的时候,额外判断:如果当前前缀和模 k 等于 0,且下标满足长度条件,先计入答案。
  5. 当数组长度小于 k+1,直接输出 0,不可能存在合法子数组。
  6. 遍历 map 里每一组余数对应的下标列表。对于列表中每一个下标,利用 lower_bound 二分查找第一个大于等于 当前下标 + k + 1 的位置。该位置往后所有元素,都可以和当前下标组成合法下标对,数量累加到答案。
  7. 最后输出统计好的答案。

思路关键点

  1. 同余转化:子数组和模 k 为 0 → 两个前缀和余数相等。
  2. 有序数组二分:同一个余数下标的数组递增,二分快速统计满足下标距离条件的配对数量。
  3. 提前特判:数组太短直接输出 0,减少无效计算。
    代码如下:
    image
posted @ 2026-10-20 08:51  事事随风散  阅读(3)  评论(0)    收藏  举报