蓝桥杯2017真题10k倍区间数
10、k倍区间
1、题目
标题: 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
题目解析:区域片段求和问题,我们可以用前缀和,或者区段和,树状数组
本题连续区间和我们采用前缀数组,进行首次求解,最终用数学问题优化
- 前缀解法
public static void main(String[] args) throws FileNotFoundException {
// System.setIn(new FileInputStream(new File("D:/Java_code/举起蓝桥杯/真题/data/in2.txt")));
Scanner scanner = new Scanner(System.in);
int nums = scanner.nextInt();
int k = scanner.nextInt();
int[] arr = new int[nums + 1];
int[] sum = new int[nums + 1];
for (int i = 1; i < nums + 1; i++) {
arr[i] = scanner.nextInt();
sum[i] = sum[i - 1] + arr[i];
}
int count = 0;
for (int i = 1; i < nums + 1; i++) {
for (int j = i; j < nums + 1; j++) {
if ((sum[j] - sum[i - 1]) % k == 0) {
count++;
}
}
}
System.out.println(count);
}
复杂度:100000 * 100000*100000,肯定超时,需要算很久
- 但是这个方法要记住,前缀数组求连续区间和,使用一个数组sum【i】表示原数组前 i 的和,注意都要从 1 开始,不然不方便
- 然后再两层循环遍历 sum数组,可以遍历出每个区间的和
优化:
static int[] arr;
static int[] sum;
static Map<Integer, Long> map = new HashMap<>();
public static void main(String[] args) throws FileNotFoundException {
System.setIn(new FileInputStream(new File("D:/Java_code/举起蓝桥杯/真题/data/in7.txt")));
Scanner scanner = new Scanner(System.in);
int nums = scanner.nextInt();
int k = scanner.nextInt();
arr = new int[nums + 1];
sum = new int[nums + 1];
map.put(0, 1l);
for (int i = 1; i < nums + 1; i++) {
arr[i] = scanner.nextInt();
sum[i] = (sum[i - 1] + arr[i]) % k;
if (map.get(sum[i]) == null) {
map.put(sum[i], 1l);
} else {
map.put(sum[i], map.get(sum[i]) + 1);
}
}
long count = 0;
for (int i = 0; i < k; i++) {
Long cnt = map.get(i);
if (cnt == null) {
cnt = 0l;
}
count += (cnt*(cnt - 1)) >> 1;
}
System.out.println(count);
}
解题思路:
数学知识:如果两个数对同一个数取余相等,那么这两个数的差一定能整除那个数,也就是:
若 a%k = c && b%k = c 则 ( a - b)% k = 0;
这样就可以设计sum[i]为arr[i] 前i项取余的结果,再用map进行记录看相同的余数的连续数组和有多少个,
然后在 随便选两个就能整除 k,相当于数学中的组合 !