问题 E: k倍区间
时间限制: 1 Sec 内存限制: 128 MB
提交: 145 解决: 44
[提交][状态][讨论版]
题目描述
给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。
你能求出数列中总共有多少个K倍区间吗?
输入
每个数据包含多组输入数据
第一行包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)
输出
输出一个整数,代表K倍区间的数目。
样例输入
5
2 1 2 3 4 5
样例输出
6
提示
思路:一开始想查找长度是1,2~n的子串,然后求和,但是时间复杂度是n^3,超时
后来想将每一项都变为前i项的和,复杂度变为n^2,但还是超时,
如果第i项对k取余的得到的数相同就说明它们相减可以整除k,复杂度为n,所以利用前缀和来求解为最佳方案(记住要最后加上对k取余结果为0的数的个数,它们本身就符合条件)。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[100100],b[100100],c[100100];
int main(void)
{
int n,k,i,j,res;
while(~scanf("%d %d",&n,&k))
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
res=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=b[i-1]+a[i];
int tp=b[i]%k;
res+=c[tp];
c[tp]++;
}
printf("%d\n",c[0]+res);
}
return 0;
}