ABC146E 题解

发布时间 2023-05-22 21:33:25作者: liangbowen

前言

题目传送门!

更好的阅读体验?

简单题,whk 的时候就秒了,但是不知道为什么很喜欢这题,就来写题解啦!

(还有一个原因是,现有题解都不知道在讲啥东西。)

思路

区间求和,容易想到前缀和。题目等价于,有多少个 \(sum_r - sum_{l-1} \equiv r-l+1 \pmod k\)

比较有趣的是移项,右边的都移到左边去,发现等价于求 \((sum_r - r) - \Big(sum_{l-1} - (l-1)\Big) \equiv 0 \pmod k\)

所以维护 \(val_i=(sum_i - i)\mod k\) 是否相同就完事了,上 map

代码

细节有两个:

  1. 注意算上 \(val_0\),因为 \((l-1)\) 可能跑到 \(0\) 去。
  2. 超出区间范围要剔除。
#include <iostream>
#include <cstdio>
#include <unordered_map>
using namespace std;
int val[200005];
unordered_map <int, int> cnt;
int main()
{
	int n, k;
	scanf("%d%d", &n, &k);
	long long ans = 0, sum = 0;
	
	val[0] = 0, cnt[0]++;
	for (int i = 1; i <= n; i++)
	{
		int x;
		scanf("%d", &x), x %= k, sum += x;
		val[i] = ((sum - i) % k + k) % k;
		if (i >= k) cnt[val[i - k]]--;
		ans += cnt[val[i]], cnt[val[i]]++;
	}
	cout << ans;
	return 0;
}

希望能帮助到大家!