K倍区间 Acwing 1230

题意:

给你一个长度为n的序列和一个k,问在这个序列中有多少个连续的子序列之和(区间和)是k的倍数。

这是一道蓝桥杯原题,最开始就想着二重循环去骗分,最后实在不知道咋做了看了y总的视频,我才纠正了以前的一个错误(a-b)%p = a%p-b%p。然后我就恍然大悟了。

思路:

首先肯定是求一个前缀和,然和按照暴力的做法我们应该是枚举区间,但是这里有所不同我们枚举的是右区间。为社么是右区间呢? 暴力的做法我们应该去判断 ( s [ r ] − s [ l − 1 ] )   m o d   k = = 0 (s[r]-s[l-1]) \ mod \ k == 0 (s[r]s[l1]) mod k==0是否成立。但是我们将上式化简, s [ r ]   m o d   k = s [ l − 1 ]   m o d   k s[r] \ mod \ k = s[l-1] \ mod \ k s[r] mod k=s[l1] mod k是否成立就是了。那么到这里我们就可以看我们如果枚举右端点,我们看在他前面 s [ r ]   m o d   k s[r] \ mod \ k s[r] mod k 这个数出现了多少次就可了对吧,如果我们枚举左端点就不好去记录右边的模数出现情况。特殊的一点我们s[0] = 0,所以余数为0的个数起始就有一个。

#include<bits/stdc++.h>

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr)
#define endl "\n"
#define int long long

using namespace std;

const int N = 2e5+10, mod = 1e9+7;

int n, _, r, k;
int arr[N];
int cnt[N];

signed main()
{
	IOS;
	cout << 0 % 2 << endl;
	cin >> n >> k;
	for(int i = 1; i <= n; i ++) cin >> arr[i], arr[i] += arr[i-1]; \\计算前缀和

	int res= 0;
	cnt[0] = 1;\\s[0] = 0
	for(int i = 1; i <= n; i ++) \\枚举右端点
	{
		res += cnt[arr[i] % k];
		cnt[arr[i] % k]++;
	}
	cout << res << endl;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值