前缀和的一个神奇算法,这道题暴力是遍历前缀和的差,也就是遍历所有区间和看他是不是能不能正好除尽k
这道题的技巧是将所有前缀和和k求余
按照求余的结果放在一个数组中
那么余数为0的前缀和a一定满足要求([0,a])
余数相同的两两组合范围相减也符合要求,所以有Cn2即 (v[i]*(v[i]-1))/2个
那么就把复杂度为O(n2)的循环遍历前缀和算法降低为复杂度为O(n)的算前缀和余数分类的算法。值得学习。
- import java.util.Scanner;
- // 1:无需package
- // 2: 类名必须Main, 不可修改
-
- public class Main {
- public static void main(String[] args) {
- Scanner scan = new Scanner(System.in);
- int n = scan.nextInt();
- int k = scan.nextInt();
- long[] q = new long[n+1];
- long[] v = new long[k];
- for(int i = 1;i <= n;i++){
- q[i] = scan.nextInt() + q[i-1];
- v[(int)(q[i]%k)]++;
- }
- long ans = 0;
- ans += v[0];
- for(int i = 0;i < k;i++){
- ans += (v[i]*(v[i]-1))/2;
- }
-
- System.out.println(ans);
- //在此输入您的代码...
- scan.close();
- }
- }