题目描述
给定一个长度为 N 的数列,A1,A2,…AN,如果其中一段连续的子序列 Ai,Ai+1,…Aj 之和是 K 的倍数,我们就称这个区间 [i,j] 是 K 倍区间。
你能求出数列中总共有多少个 K 倍区间吗?
输入格式
第一行包含两个整数 N 和 K。
以下 N 行每行包含一个整数 Ai。
输出格式
输出一个整数,代表 K 倍区间的数目。
输入样例
5 2
1
2
3
4
5
输出样例:
6
解题思路
从每日一题来的
- 求前缀和
- 有了前缀和,那么前[j, i]区间的和就可以通过s[i] - s[j - 1]得到
- 假设我们以i为结尾,求这之前有多少个坐标对的和可以被K整除,列出公式
(s[i] - s[i - 1]) / k, (s[i] - s[i - 2]) / k, ..., (s[i] - s[0]) / k
- 那我们想要知道有多少个区间的和可以被K整除,其实就是求s[0]到s[i - 1]中有多少个数和s[i]同余
- 那么我们在遍历的过程中记录每个s[i] % k出现次数,i就有count[s[i] % k]个区间的和可以被K整除
代码
import java.util.*;
public class Main{
static int N = 100010;
static int[] s = new int[N];
static int[] count = new int[N];
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
count[0] ++;
long ans = 0;
for(int i = 1; i <= n; i ++){
int num = sc.nextInt();
s[i] = (s[i - 1] + num) % k;
ans += count[s[i]];
count[s[i]] ++;
}
System.out.println(ans);
}
}