历届试题 k倍区间
时间限制:2.0s 内存限制:256.0MB
问题描述
给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。
你能求出数列中总共有多少个K倍区间吗?
你能求出数列中总共有多少个K倍区间吗?
输入格式
第一行包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)
输出格式
输出一个整数,代表K倍区间的数目。
样例输入
5 2
1
2
3
4
5
1
2
3
4
5
样例输出
6
数据规模和约定
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms
CPU消耗 < 2000ms
思路:用pre数组预处理出前n项和,则当 (pre[j]-pre[i-1])%k==0时满足题意
移项得pre[j]%k==pre[i-1]%k,所以计算pre数组时只需储存其%k的值,然后记录为该值的个数
要注意的是当pre%k==0时,不仅可以与其下标前所有%k==0的地方形成区间,还可以与第一位形成区间,所以最后要再加上%k==0的个数
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#define max_ 100010
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
int sum[max_],num[max_];
int n,k;
int main(int argc, char const *argv[]) {
scanf("%d%d",&n,&k);
ll cnt=0;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
sum[i]=(sum[i-1]+x)%k;
cnt+=num[sum[i]];
num[sum[i]]++;
}
printf("%lld\n",cnt+num[0]);
return 0;
}