🍻最大和
属于走楼梯、跳格子问题的升级版,通过另一种方式告诉你当前格子能够跳到的最远距离,究其本质,还是一样的。
import java.util.*;
import java.io.*;
public class Main {
static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
// 线性筛求素数,用于后续判断每格能够到达的最远距离
int[] prime = new int[10000];
int cnt = 0;
boolean[] isprime = new boolean[10001];
for (int i = 2; i <= 10000; i++) {
if (isprime[i] == false) {
prime[cnt++] = i;
}
for (int j = 0; j < cnt; j++) {
if (prime[j] * i > 10000) break;
isprime[prime[j] * i] = true;
if (i % prime[j] == 0) break;
}
}
int n = Integer.parseInt(reader.readLine().trim());
int[] map = new int[n + 1];
String[] input = reader.readLine().trim().split(" ");
for (int i = 0; i < n; i++) map[i + 1] = Integer.parseInt(input[i]);
// 记录能够到达的最远距离
int[] len = new int[n + 1];
len[n] = n;
len[n - 1] = n;
for (int i = 1; i < n - 1; i++) {
for (int j = 0; j < cnt; j++) {
if ((n - i) % prime[j] == 0) {
len[i] = i + prime[j];
break;
}
}
}
// dp[i]以第i个格子结尾能够产生的最大价值
int[] dp = new int[n + 1];
for (int i = 1; i <= n; i++) dp[i] = map[i];
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
if (len[j] >= i) {
dp[i] = Math.max(dp[i], dp[j] + map[i]);
}
}
}
System.out.println(dp[n]);
}
}
🧊染色时间
关键是要保证每个方块在最短的时间内被染色,可以用一个数组记录染色完某一个方块所需的时间,然后遍历所有时间,其中的最大值就是染色完所有方格需要的时间。
import java.util.*;
import java.io.*;
class node {
int x, y;
node () {}
node (int x, int y) {
this.x = x;
this.y = y;
}
}
public class Main {
static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
String[] input = reader.readLine().trim().split(" ");
int n = Integer.parseInt(input[0]);
int m = Integer.parseInt(input[1]);
int[][] map = new int[n][m];
for (int i = 0; i < n; i++) {
input = reader.readLine().trim().split(" ");
for (int j = 0; j < m; j++) {
map[i][j] = Integer.parseInt(input[j]);
}
}
Queue<node> queue = new LinkedList<>();
int[] x = new int[] {0,0,1,-1};
int[] y = new int[] {1,-1,0,0};
// 记录染色到每个方格的时间
int[][] time = new int[n][m];
for (int i = 0; i < n; i++) Arrays.fill(time[i], 0x3f3f3f3f);
// 起点位于第一格
time[0][0] = map[0][0];
queue.offer(new node(0, 0));
while (!queue.isEmpty()) {
node cur = queue.poll();
int t = time[cur.x][cur.y];
for (int i = 0; i < 4; i++) {
int tx = cur.x + x[i];
int ty = cur.y + y[i];
if (tx < 0 || ty < 0 || tx >= n || ty >= m) continue;
// 保证染色到达的方块时间是最短的
// 保证方块是被最短到达的时间染色
if (t + map[tx][ty] < time[tx][ty]) {
time[tx][ty] = t + map[tx][ty];
queue.offer(new node(tx, ty));
}
}
}
int ans = 0xc0c0c0c0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ans = Math.max(ans, time[i][j]);
}
}
System.out.println(ans);
}
}
🍺k倍区间
浅放一个错解,用的是之前的k倍区间题目的答案改的,但是本题问题在于负数取余的处理。
import java.util.*;
import java.io.*;
public class Main {
static BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
String[] input = reader.readLine().trim().split(" ");
int n = Integer.parseInt(input[0]);
int k = Integer.parseInt(input[1]);
int[] num = new int[n];
input = reader.readLine().trim().split(" ");
for (int i = 0; i < n; i++) {
num[i] = Integer.parseInt(input[i]);
}
// 前缀和
int[] preSum = new int[n + 1];
for (int i = 1; i <= n; i++) {
preSum[i] = (preSum[i - 1] + num[i - 1]);
}
// 记录前缀和的个数
HashMap<Integer, Integer> map = new HashMap<>();
// map.put(0, 1);
int ans = 0;
for (int i = 1; i <= n; i++) {
// k的非负整数倍(>=0的整数)
int cur = preSum[i];
if (cur < 0) continue; // 负数不考虑
cur %= k;
if (map.containsKey(cur) && cur >= 0) {
ans += map.get(cur);
}
map.put(cur, map.getOrDefault(cur, 0) + 1);
}
System.out.println(ans);
}
}