此题根据大佬的博文改写,膜拜大佬!
题目
给定一个长度为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倍区间的数目。
思路
边读入边处理;
假如j之前(包括j)所有数的和为sum[j];
由于K倍区间满足(sum[j]-sum[i-1])%k=0;
变形得sum[j]%k =sum[i-1]%k;
即只需找在当前位置之前有多少和自己的sum%k相等;
每次循环都计算出sum%k,并寻找之前有多少个余数相同的,累加起来,但这些还缺少一种情况,即sum%k = 0的情况,这种可以从0到此形成K倍区间;
由于对k取余,余数不会超过k,只需申请k个空间存储;
这种算法的时间复杂度为o(n);
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n,k,sum = 0;
long count = 0;
n = sc.nextInt();
k = sc.nextInt();
int[] cnt = new int[k];
for (int i = 0; i < n; i++) {
sum = (sum + sc.nextInt()) % k;
count += cnt[sum]++;
}
count += cnt[0];
System.out.println(count);
sc.close();
}
}