k倍区间c++

题目

输入样例:

5 2
1
2
3
4
5

输出样例:

6
思路

本题默认所有读者已经理解了如何求前缀和。

        可以利用双层循环分别枚举左端点和右端点即可枚举完所有区间,而对于每个区间,利用一维前缀和判断它是否是一个k倍区间,是的话答案数+1,但时间复杂度为O(10^10),超时。代码如下:

//s[]为前缀和数组, res 为总区间数
for (int r = 1; r <= n; r ++)
for (int l = 1; l <= r; l ++)
{
	if ((s[r] - s[l - 1]) % k == 0)res ++;
}

        实际上,这个双层循环可以理解为,在右端点r固定,l 在 0 ~ r - 1 之间变化的情况下,可以找到多少个满足 (s[r] - s[l]) % k == 0的区间,判断条件变换一下得:(s[r] % k - s[l] % k) % k == 0,即在 0 ~ r - 1 之间能找到有多少个s[l] % k 等于 s[r] % k,使得[l, r]构成k倍区间。而 s[r] % k的个数可以在r从前往后遍历过程中用一个数组cnt统计出来,cnt[i]代表 s[r]%k余数等于i的个数。

        特别注意,当s[i] % k 等于0时,说明s[i]本身即可构成一个k倍区间,因此cnt[0]要预置为1,这样当遇到第一个s[i] % k==0时就可以统计到答案res中去了。

代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
LL a[N], cnt[N];

int main()
{
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int n, k;
  cin >> n >> k;
  //求前缀和
  for (int i = 1; i <= n; i ++)
  {
    cin >> a[i];
    a[i] += a[i - 1];
  }
  
  LL res = 0;
  cnt[0] = 1;
  for (int i = 1; i <= n; i ++)
  {
    res += cnt[a[i] % k] ++;
  }
  cout << res;
  return 0;
}

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值