Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dd5beed

Browse files
committed
第161场双周赛T1~T4 & 第459场周赛T1~T4 (8)
1 parent b9af3de commit dd5beed

16 files changed

+714
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
public class Solution3618 {
2+
public long splitArray(int[] nums) {
3+
int n = nums.length;
4+
long sumA = 0, sumB = 0;
5+
for (int i = 0; i < n; i++) {
6+
if (isPrime(i)) sumA += nums[i];
7+
else sumB += nums[i];
8+
}
9+
return Math.abs(sumA - sumB);
10+
}
11+
12+
private boolean isPrime(long num) {
13+
if (num < 2) {
14+
return false;
15+
}
16+
for (long i = 2; i * i <= num; ++i) {
17+
if (num % i == 0) {
18+
return false;
19+
}
20+
}
21+
return true;
22+
}
23+
}
24+
/*
25+
3618. 根据质数下标分割数组
26+
https://leetcode.cn/problems/split-array-by-prime-indices/description/
27+
28+
第 161 场双周赛 T1。
29+
30+
给你一个整数数组 nums。
31+
根据以下规则将 nums 分割成两个数组 A 和 B:
32+
- nums 中位于 质数 下标的元素必须放入数组 A。
33+
- 所有其他元素必须放入数组 B。
34+
返回两个数组和的 绝对 差值:|sum(A) - sum(B)|。
35+
质数 是一个大于 1 的自然数,它只有两个因子,1和它本身。
36+
注意:空数组的和为 0。
37+
提示:
38+
1 <= nums.length <= 10^5
39+
-10^9 <= nums[i] <= 10^9
40+
41+
中国时间 2025年07月19日 周六 22:30
42+
上海。
43+
模拟。判断素数。
44+
*/
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
public class Solution3619 {
2+
private static final int[][] DIRECTIONS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
3+
private int[][] grid;
4+
private int m, n;
5+
6+
public int countIslands(int[][] grid, int k) {
7+
this.grid = grid;
8+
m = grid.length;
9+
n = grid[0].length;
10+
int ans = 0;
11+
for (int i = 0; i < m; i++) {
12+
for (int j = 0; j < n; j++) {
13+
if (grid[i][j] > 0 && dfs(i, j) % k == 0) {
14+
ans++;
15+
}
16+
}
17+
}
18+
return ans;
19+
}
20+
21+
private long dfs(int x, int y) {
22+
long res = grid[x][y];
23+
grid[x][y] = 0; // 标记为访问过
24+
for (int[] d : DIRECTIONS) {
25+
int nx = x + d[0];
26+
int ny = y + d[1];
27+
if (0 <= nx && nx < m && 0 <= ny && ny < n && grid[nx][ny] > 0) {
28+
res += dfs(nx, ny);
29+
}
30+
}
31+
return res;
32+
}
33+
}
34+
/*
35+
3619. 总价值可以被 K 整除的岛屿数目
36+
https://leetcode.cn/problems/count-islands-with-total-value-divisible-by-k/description/
37+
38+
第 161 场双周赛 T2。
39+
40+
给你一个 m x n 的矩阵 grid 和一个正整数 k。一个 岛屿 是由 正 整数(表示陆地)组成的,并且陆地间 四周 连通(水平或垂直)。
41+
一个岛屿的总价值是该岛屿中所有单元格的值之和。
42+
返回总价值可以被 k 整除 的岛屿数量。
43+
提示:
44+
m == grid.length
45+
n == grid[i].length
46+
1 <= m, n <= 1000
47+
1 <= m * n <= 10^5
48+
0 <= grid[i][j] <= 10^6
49+
1 <= k < = 10^6
50+
51+
网格图 DFS。
52+
时间复杂度:O(mn)。
53+
*/
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import java.util.ArrayDeque;
2+
import java.util.ArrayList;
3+
import java.util.Arrays;
4+
import java.util.List;
5+
import java.util.Queue;
6+
7+
public class Solution3620 {
8+
private List<int[]>[] g;
9+
private long k;
10+
11+
public int findMaxPathScore(int[][] edges, boolean[] online, long k) {
12+
int n = online.length;
13+
g = new ArrayList[n];
14+
Arrays.setAll(g, e -> new ArrayList<>());
15+
this.k = k;
16+
int[] deg = new int[n];
17+
int maxWt = -1;
18+
for (int[] e : edges) {
19+
int x = e[0], y = e[1], wt = e[2];
20+
if (online[x] && online[y]) {
21+
g[x].add(new int[]{y, wt});
22+
deg[y]++;
23+
if (x == 0) {
24+
maxWt = Math.max(maxWt, wt);
25+
}
26+
}
27+
}
28+
29+
// 先清理无法从 0 到达的边
30+
Queue<Integer> q = new ArrayDeque<>();
31+
for (int i = 1; i < n; i++) {
32+
if (deg[i] == 0) {
33+
q.offer(i);
34+
}
35+
}
36+
while (!q.isEmpty()) {
37+
int x = q.poll();
38+
for (int[] e : g[x]) {
39+
int y = e[0];
40+
if (--deg[y] == 0 && y > 0) {
41+
q.offer(y);
42+
}
43+
}
44+
}
45+
long[] f = new long[n];
46+
47+
int left = 0;
48+
int right = maxWt + 1;
49+
while (left < right) {
50+
int mid = left + (right - left) / 2;
51+
// 边界二分 F, F,..., F, [T, T,..., T]
52+
// ----------------------^
53+
if (!check(mid, deg.clone(), f)) {
54+
right = mid;
55+
} else {
56+
left = mid + 1;
57+
}
58+
}
59+
return left - 1;
60+
}
61+
62+
private boolean check(int lower, int[] deg, long[] f) {
63+
Arrays.fill(f, Long.MAX_VALUE / 2); // 除 2 防止加法溢出
64+
f[0] = 0;
65+
Queue<Integer> q = new ArrayDeque<>();
66+
q.offer(0);
67+
while (!q.isEmpty()) {
68+
int x = q.poll();
69+
if (x == g.length - 1) {
70+
return f[x] <= k;
71+
}
72+
for (int[] e : g[x]) {
73+
int y = e[0], wt = e[1];
74+
if (wt >= lower) {
75+
f[y] = Math.min(f[y], f[x] + wt);
76+
}
77+
if (--deg[y] == 0) {
78+
q.offer(y);
79+
}
80+
}
81+
}
82+
return false; // 无法到达 n-1
83+
}
84+
}
85+
/*
86+
3620. 恢复网络路径
87+
https://leetcode.cn/problems/network-recovery-pathways/description/
88+
89+
第 161 场双周赛 T3。
90+
91+
给你一个包含 n 个节点(编号从 0 到 n - 1)的有向无环图。图由长度为 m 的二维数组 edges 表示,其中 edges[i] = [ui, vi, costi] 表示从节点 ui 到节点 vi 的单向通信,恢复成本为 costi。
92+
一些节点可能处于离线状态。给定一个布尔数组 online,其中 online[i] = true 表示节点 i 在线。节点 0 和 n - 1 始终在线。
93+
从 0 到 n - 1 的路径如果满足以下条件,那么它是 有效 的:
94+
- 路径上的所有中间节点都在线。
95+
- 路径上所有边的总恢复成本不超过 k。
96+
对于每条有效路径,其 分数 定义为该路径上的最小边成本。
97+
返回所有有效路径中的 最大 路径分数(即最大 最小 边成本)。如果没有有效路径,则返回 -1。
98+
提示:
99+
n == online.length
100+
2 <= n <= 5 * 10^4
101+
0 <= m == edges.length <= min(105, n * (n - 1) / 2)
102+
edges[i] = [ui, vi, costi]
103+
0 <= ui, vi < n
104+
ui != vi
105+
0 <= costi <= 10^9
106+
0 <= k <= 5 * 10^13
107+
online[i] 是 true 或 false,且 online[0] 和 online[n - 1] 均为 true。
108+
给定的图是一个有向无环图。
109+
110+
二分答案 + DAG DP / 拓扑排序。
111+
时间复杂度:O((n+m)logU)
112+
*/
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3621 {
4+
public long popcountDepth(long num, int k) {
5+
this.s = Long.toBinaryString(num).toCharArray();
6+
int n = s.length;
7+
if (k == 0) return 1;
8+
if (k == 1) return n - 1;
9+
10+
memo = new long[n][n + 1];
11+
for (int i = 0; i < n; i++) {
12+
Arrays.fill(memo[i], -1);
13+
}
14+
15+
long ans = 0;
16+
int[] f = new int[n + 1];
17+
for (int i = 1; i <= n; i++) {
18+
f[i] = f[Integer.bitCount(i)] + 1;
19+
if (f[i] == k) { // 注意
20+
ans += f(0, i, true);
21+
}
22+
}
23+
return ans;
24+
}
25+
26+
private char[] s;
27+
private long[][] memo;
28+
29+
private long f(int i, int left1, boolean isLimit) {
30+
if (i == s.length) {
31+
return left1 == 0 ? 1 : 0; // 注意
32+
}
33+
if (!isLimit && memo[i][left1] != -1) return memo[i][left1];
34+
long res = 0;
35+
int up = isLimit ? s[i] - '0' : 1;
36+
for (int d = 0; d <= Math.min(up, left1); d++) {
37+
res += f(i + 1, left1 - d, isLimit && d == up);
38+
}
39+
if (!isLimit) {
40+
memo[i][left1] = res;
41+
}
42+
return res;
43+
}
44+
}
45+
/*
46+
3621. 位计数深度为 K 的整数数目 I
47+
https://leetcode.cn/problems/number-of-integers-with-popcount-depth-equal-to-k-i/description/
48+
49+
第 161 场双周赛 T4。
50+
51+
给你两个整数 n 和 k。
52+
对于任意正整数 x,定义以下序列:
53+
- p0 = x
54+
- pi+1 = popcount(pi),对于所有 i >= 0,其中 popcount(y) 是 y 的二进制表示中 1 的数量。
55+
这个序列最终会达到值 1。
56+
x 的 popcount-depth (位计数深度)定义为使得 pd = 1 的 最小 整数 d >= 0。
57+
例如,如果 x = 7(二进制表示 "111")。那么,序列是:7 → 3 → 2 → 1,所以 7 的 popcount-depth 是 3。
58+
你的任务是确定范围 [1, n] 中 popcount-depth 恰好 等于 k 的整数数量。
59+
返回这些整数的数量。
60+
提示:
61+
1 <= n <= 10^15
62+
0 <= k <= 5
63+
64+
数位 DP。同 CF914C。
65+
时间复杂度:O(log^2(n))
66+
相似题目: 3352. 统计小于 N 的 K 可约简整数
67+
https://leetcode.cn/problems/count-k-reducible-numbers-less-than-n/description/
68+
C. Travelling Salesman and Special Numbers
69+
https://codeforces.com/contest/914/problem/C
70+
rating 2341 (clist.by)
71+
*/
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
public class Solution3622 {
2+
public boolean checkDivisibility(int n) {
3+
return n % (digitSum(n) + digitProd(n)) == 0;
4+
}
5+
6+
private int digitProd(int x) {
7+
int res = 1;
8+
while (x > 0) {
9+
res *= x % 10;
10+
x /= 10;
11+
}
12+
return res;
13+
}
14+
15+
private int digitSum(int x) {
16+
int sum = 0;
17+
while (x > 0) {
18+
sum += x % 10;
19+
x /= 10;
20+
}
21+
return sum;
22+
}
23+
}
24+
/*
25+
3622. 判断整除性
26+
https://leetcode.cn/problems/check-divisibility-by-digit-sum-and-product/description/
27+
28+
第 459 场周赛 T1。
29+
30+
给你一个正整数 n。请判断 n 是否可以被以下两值之和 整除:
31+
- n 的 数字和(即其各个位数之和)。
32+
- n 的 数字积(即其各个位数之积)。
33+
如果 n 能被该和整除,返回 true;否则,返回 false。
34+
提示:
35+
1 <= n <= 10^6
36+
37+
中国时间 2025年07月20日 周日 10:30
38+
上海。
39+
模拟。
40+
*/
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import java.util.HashMap;
2+
import java.util.Map;
3+
4+
public class Solution3623 {
5+
private static final int MOD = (int) (1e9 + 7);
6+
7+
public int countTrapezoids(int[][] points) {
8+
Map<Integer, Integer> cnt = new HashMap<>();
9+
for (int[] p : points) {
10+
cnt.merge(p[1], 1, Integer::sum); // 统计每一行(水平线)有多少个点
11+
}
12+
13+
long ans = 0, s = 0;
14+
for (int c : cnt.values()) {
15+
long k = (long) c * (c - 1) / 2;
16+
ans += s * k;
17+
s += k;
18+
}
19+
return (int) (ans % MOD);
20+
}
21+
}
22+
/*
23+
3623. 统计梯形的数目 I
24+
https://leetcode.cn/problems/count-number-of-trapezoids-i/description/
25+
26+
第 459 场周赛 T2。
27+
28+
给你一个二维整数数组 points,其中 points[i] = [xi, yi] 表示第 i 个点在笛卡尔平面上的坐标。
29+
水平梯形 是一种凸四边形,具有 至少一对 水平边(即平行于 x 轴的边)。两条直线平行当且仅当它们的斜率相同。
30+
返回可以从 points 中任意选择四个不同点组成的 水平梯形 数量。
31+
由于答案可能非常大,请返回结果对 10^9 + 7 取余数后的值。
32+
提示:
33+
4 <= points.length <= 10^5
34+
–10^8 <= xi, yi <= 10^8
35+
所有点两两不同。
36+
37+
枚举右,维护左
38+
时间复杂度 O(n)。
39+
*/

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /