题目描述
给定一个长度为 NN 的数列,A1,A2,⋯ANA1,A2,⋯AN,如果其中一段连续的子序列 Ai,Ai+1,⋯Aj(i≤j)Ai,Ai+1,⋯Aj(i≤j) 之和是 KK 的倍数,我们就称这个区间 [i,j][i,j] 是 KK 倍区间。
你能求出数列中总共有多少个 KK 倍区间吗?
输入格式
第一行包含两个整数 NN 和 KK(1≤N,K≤105)(1≤N,K≤105)。
以下 NN 行每行包含一个整数 AiAi(1≤Ai≤105)(1≤Ai≤105)。
输出格式
输出一个整数,代表 KK 倍区间的数目。
输入输出样例
输入
5 2 1 2 3 4 5
输出
6
说明/提示
时限 2 秒, 256M。蓝桥杯 2017 年第八届
传统暴力肯定会超时,所以用同余定理优化了
同余定理:如果a%c=b%c,那么(a+b)%c=0,(a-b)%c=0
例如:如果两个区间同余就说明这两个区间多了一个K倍区间,1 2 3 4 5 6可以看做:
0 1 2 3 4 5
sum 0 1 3 6 10 15
arr[]数组记录的是同余区间个数,比如如果f[0]=2,再出现一个区间和%k==0的话,sum1=sum1+1*2,因为f[0]里面有两个%k=0的区间,再出现的区间分别与各区间之中多了一个k区间。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
final Scanner scan = new Scanner(System.in);
int N=scan.nextInt();
int k=scan.nextInt();
int[] arr=new int[k];
long sum=0,sum1=0;
arr[0]=1;
for(int i=0;i<N;i++){
sum=sum+scan.nextLong();
sum1=sum1+arr[(int)(sum%k)];
arr[(int)(sum%k)]++;
}
System.out.println(sum1);
}
}