HackerRank Weekly Challenges - Week 6: Consecutive Subsequences 你有余我也有余

本文介绍了一种高效的算法来解决给定序列中能够被特定整数整除的连续子串数量的问题。算法利用前缀和与哈希映射,通过观察连续子串和对给定整数取模后的余数相等的特性,快速计算出满足条件的子串总数。详细步骤包括计算前缀和、映射余数、统计符合要求的子串数量,并考虑单个整数作为有效子串的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:Consecutive Subsequences

题目大意:给定一个包含 n(1 ≤ n ≤ 10^6)个正整数的序列 a[n],以及一个整数 k(1 ≤ k ≤ 100),求能够被 k 整除的连续的子串的个数。其中序列中每个元素的大小范围:1 ≤ a[i] ≤ 10^4

大致思路:如果直接存储序列的前缀和,再通过两层循环得到所有连续子串的和必然会超时,但是前缀和还是要用到的,我们把序列的前缀和存在数组 sum[n] 中。通过观察可以发现,若 a1,a2,a3....,ax 以及 a1,a2,a3....,ay(y>x)的和除以 k 的余数相同,则 ax....ay 的和就能整除 k,即 sum[x]%k == sum[y]%k 时,就存在一个符合条件的连续子串。所以,可以使用类似哈希的方式,将每个前缀和对 k 取余,取余结果相同的就映射到同一个桶中,并累加桶中元素的个数。对于同一个桶中的任意两个元素 sum[i] 和 sum[j],则从 i 至 j 的连续子串和即可整除 k,故整个桶中符合条件的子串个数即为哈希桶元素个数的组合数 C(n,2)。同时,由于单个整数也是符合条件的子串,故还需加上桶0的大小。另外,由于题目给定的数据上限较大,使用 int 有可能溢出,所以使用 long long。具体实现如下:

#include <cstdio>
#include <cstring>

long long a[1000005];
long long b[105];

int main() {
	long long T, n, k, num;
	scanf("%lld",&T);
	while(T--) {
		scanf("%lld%lld",&n,&k);
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		long long count = 0;		
		for(long long i=1; i<=n; i++) {
			scanf("%lld", &num);
			a[i] = num + a[i-1];
			long long rem = a[i] % k;
			b[rem]++;
		}
		count += b[0];
		for(long long i=0; i<k; i++) {
			count += (b[i]-1) * (b[i]) / 2;
		}
		printf("%lld\n", count);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值