蓝桥杯:k倍区间 前缀和,同余优化

题目描述

在这里插入图片描述

思路

通过前缀和计算一个区间的累加和
区间[l, r]的累加和是前缀和数组sum[r]-sum[l-1]

如果这里暴力枚举区间端点,必定超时,于是想到:如果两个数ab之差(a-b)%k = 0,意味着 a%k = b%k,这就好办了

  • 开一个数组cnt记录,cnt[i]表示前缀和数组中,余数为isum[某个下标]有多少个
  • 然后不断枚举右端点,查询cnt数组中,与右端点同余的端点数目有多少,那么他们就可以和这个新的右端点组成cnt[sum[i]]个新区间,答案+=新区间数
  • 然后更新cnt数组,把当前右端点的%k对应的数目++,即cnt[sum[i]%k]
  • 最后别忘了加上cnt[0],因为刚好整除k的点,自己成一个长度为1的区间,而这样的区间有cnt[0]

代码

这题想法不难,主要是优化的时候,同余能否想到,这样使得代码的复杂度变为O(n)

还有,注意用 long long ,读取用scanf加速

#include <bits/stdc++.h>

using namespace std;

#define maxlen 100009
typedef long long ll;
ll a[maxlen];
ll cnt[maxlen] = {0};

int main()
{
	int n, k;
	cin>>n>>k;
	a[0] = 0;
	ll ans = 0;
	for(int i=1; i<=n; i++)
	{
		scanf("%ld", &a[i]);
		a[i] += a[i-1];
		ans += cnt[a[i]%k];
		cnt[a[i]%k]++;
	}
	cout<<ans+cnt[0]<<endl;
	
	return 0;
}
发布了171 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44176696/article/details/104585365