第八届蓝桥杯 JavaB k倍区间
标题: k倍区间
给定一个长度为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倍区间的数目。
例如,
输入:
5 2
1
2
3
4
5
程序应该输出:
6
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms
法一:
思路:
* 首先统计前缀和sum[i] 表示A1+A2+…+Ai.所以对于任意一段区间[l,r]的和就是sum[r]-sum[l-1].如果要保证这个区间和为K倍数就是:(sum[r]-sum[l-1])%k == 0.变形后就是:sum[r]%k==sum[l-1]%k,所以我们计算前缀和的时候顺带模K,然后统计前缀和中相同的数据就行了。复杂度O(n).
参考:YzlCoder
int[] sum记录前缀和对k的余数。int[] c,c[i]记录之前有几个区间对k余数为i。
最终结果加上cnt[0],因为忽略了前i个数的和取模是k的倍数的情况,即[0,i]区间和是k的倍数,因此需加上cnt[0]。
参考:i逆天耗子丶
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
/**
* 参考链接 https://blog.youkuaiyun.com/y1196645376/article/details/69718192
* https://blog.youkuaiyun.com/qq_34594236/article/details/70845223
* https://blog.youkuaiyun.com/za30312/article/details/69681146
*
* @description TODO
* @author frontier
* @time 2019年3月11日 下午5:13:54
*
*/
public class 编程10K倍区间3 {
static int n, k;
static int[] sum = new int[100009];// 前缀和
static int[] cnt = new int[100009];// c[i]表前缀和mod k为i的的个数
static long count;
public static void main(String[] args) throws FileNotFoundException {
Scanner in = new Scanner(new File("src/JavaB/s8/10.txt"));
n = in.nextInt();
k = in.nextInt();
for (int i = 1; i <= n; ++i) {
sum[i] = (sum[i - 1] + in.nextInt()) % k;// 前缀和对k的余数
count += cnt[sum[i]]++;
}
System.out.println(count + cnt[0]);
}
}