【题目描述】
【思路】
对前缀和取模之后,两个相等的前缀和就能组成一个k倍区间。
对于数列 1 2 3 4 5,k = 2
对前1个数的和模k后为1,在此之前有0个前缀和取模后为1,总个数+0
对前2个数的和模k后为1,在此之前有1个前缀和取模后为1,总个数+1
对前3个数的和模k后为0,在此之前有0个前缀和取模后为0, 总个数+0
对前4个数的和模k后为0,在此之前有1个前缀和取模后为0,总个数+1
对前5个数的和模k后为1,在此之前有2个前缀和取模后为1,总个数+2
实际上就是在模相同的数里面选两个组合,计算组合数。
import java.io.*;
public class Main{
static int N = 100010;
static int [] f = new int[N];
static int [] pre = new int[N];// 前缀和
static int [] cnt = new int[N]; //记录余数是i的数的个数
public static void main(String args[])throws Exception{
BufferedReader bf= new BufferedReader(new InputStreamReader(System.in));
String s[] = bf.readLine().split(" ");
int n = Integer.parseInt(s[0]), k = Integer.parseInt(s[1]);
for(int i = 1; i <= n; i++) f[i] = Integer.parseInt(bf.readLine());
//计算前缀和
for(int i = 1; i <= n; i++) pre[i] = (pre[ i - 1] + f[i]%k) % k;
// 1 2 3 4 5
// 1 3 6 10 15
// 1 1 0 0 1
long ans = 0;
cnt[0] = 1;
for(int i = 1; i <= n; i++){
ans += cnt[ pre[i] % k ];
System.out.print(ans+" ");
cnt[ pre[i] % k]++;
System.out.println((pre[i] % k) +" "+cnt[pre[i] % k]);
}
System.out.println(ans);
}
}