给定一个长度为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
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms
解题思路:
前 i 项之和%k 与 前 j 项之和%k相等的话,那么[i - j ] 之间和一定是k的倍数
#include <stdio.h>
#define M 1000002
int num[M]={0};
int mod[M]={0}; //记录每位余数
int count[M]={0}; //记录对k取余后,每个余数出现的次数
int getC(int num);
int main(void)
{
int n=0,k=0;
int i=0;
long long sum=0;
scanf("%d %d",&n,&k);
for(i=1;i<=n;i++)
{
scanf("%d",num+i);
mod[i] = (mod[i-1]+num[i])%k; //将num[i]从第一位叠加到i位,并得对k取余,保存入mod数组
count[mod[i]]++; //记录余数出现的次数
}
sum = count[0]; //当余数为0,则说明正好是k的整数倍,sum初始化为count[0]
//比如例题[1,3]是一种情况,正好从第一位叠加到第三位是2的倍数,而叠加到第三位的和对2取余正好是0.
for(i=0;i<k;i++)
{
sum+=getC(count[i]);
}
printf("%ld",sum);
return 0;
}
//求num个数有多少个两两组合,即C(2,num);
int getC(int num)
{
return num*(num-1)/2;
}