题目描述
给定一个长度为 N 的数列,A1,A2,⋯AN,如果其中一段连续的子序列 Ai,Ai+1,⋯Aj(i≤j) 之和是 K 的倍数,我们就称这个区间 [i,j] 是 K 倍区间。
你能求出数列中总共有多少个 K 倍区间吗?
输入格式
第一行包含两个整数 N 和 K(1≤N,K≤10^5)。
以下 N 行每行包含一个整数 Ai(1≤Ai≤10^5)。
输出格式
输出一个整数,代表 K 倍区间的数目。
输入输出样例
输入 #1复制
5 2 1 2 3 4 5
输出 #1复制
6
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int k = scanner.nextInt();
long[] arr = new long[k];//前缀和模k数组
long sum = 0;
for(int i = 0;i < n;i++) {
sum += scanner.nextInt();
arr[(int)(sum % k)]++;
}
long count = arr[0];
for(int i = 0;i < arr.length;i++) {
count += (arr[i] * (arr[i] - 1) / 2);
}
System.out.print(count);
}
}
题解分析:看到题目区间求和的要求便知道题目要用前缀和来求解,此外该题还要用到同余定理:即x mod k == y mod k,则有|x - y| mod k == 0,因此如果我们找到前缀和数组求余后两个相同的余数,那么这两个前缀和中间的部分即为所求区间,如果有n个前缀和余数相同,那么就构成了n*(n-1)/2个区间。此外需要注意在计算区间数目count时不要忘记将count初始化为arr[0]即为k的倍数的前缀和。
数据量大的地方一定要用long!!!!!!!!
拓展关于差分的一些公式:
差分数组:d[i] = a[i] - a[i - 1];
差分标记:[L,R] + V = d[L] + V and d[R+1] - V ,标记后的差分数组进行前缀和得到操作后的数组