您的位置:首页 > 产品设计 > UI/UE

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

2014-07-02 17:58 603 查看
原题链接:Consecutive Subsequences

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

大致思路:如果直接存储序列的前缀和,再通过两层循环得到所有连续子串的和必然会超时,但是前缀和还是要用到的,我们把序列的前缀和存在数组 sum
中。通过观察可以发现,若 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM algorithm HackerRank