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 ef60d94

Browse files
committed
第448场周赛T1~T4 (4)
1 parent 0cace5b commit ef60d94

File tree

8 files changed

+342
-0
lines changed

8 files changed

+342
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3536 {
4+
public int maxProduct(int n) {
5+
char[] a = String.valueOf(n).toCharArray();
6+
Arrays.sort(a);
7+
int len = a.length;
8+
return (a[len - 1] - '0') * (a[len - 2] - '0');
9+
}
10+
}
11+
/*
12+
3536. 两个数字的最大乘积
13+
https://leetcode.cn/problems/maximum-product-of-two-digits/description/
14+
15+
第 448 场周赛 T1。
16+
17+
给定一个正整数 n。
18+
返回 任意两位数字 相乘所得的 最大 乘积。
19+
注意:如果某个数字在 n 中出现多次,你可以多次使用该数字。
20+
提示:
21+
10 <= n <= 10^9
22+
23+
贪心。
24+
中国时间 2025年05月04日 周日 10:30
25+
广州·中肿。五四青年节。
26+
*/
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
public class Solution3537 {
2+
private int[][] ans;
3+
private int val;
4+
5+
public int[][] specialGrid(int n) {
6+
ans = new int[1 << n][1 << n];
7+
val = 0;
8+
dfs(0, 1 << n, 0, 1 << n);
9+
return ans;
10+
}
11+
12+
private void dfs(int u, int d, int l, int r) {
13+
if (d - u == 1) {
14+
ans[u][l] = val++;
15+
return;
16+
}
17+
int m = (d - u) / 2;
18+
dfs(u, u + m, l + m, r);
19+
dfs(u + m, d, l + m, r);
20+
dfs(u + m, d, l, l + m);
21+
dfs(u, u + m, l, l + m);
22+
}
23+
}
24+
/*
25+
3537. 填充特殊网格
26+
https://leetcode.cn/problems/fill-a-special-grid/description/
27+
28+
第 448 场周赛 T2。
29+
30+
给你一个非负整数 N,表示一个 2^N x 2^N 的网格。你需要用从 0 到 2^2N - 1 的整数填充网格,使其成为一个 特殊 网格。一个网格当且仅当满足以下 所有 条件时,才能称之为 特殊 网格:
31+
- 右上角象限中的所有数字都小于右下角象限中的所有数字。
32+
- 右下角象限中的所有数字都小于左下角象限中的所有数字。
33+
- 左下角象限中的所有数字都小于左上角象限中的所有数字。
34+
- 每个象限也都是一个特殊网格。
35+
返回一个 2^N x 2^N 的特殊网格。
36+
注意:任何 1x1 的网格都是特殊网格。
37+
提示:
38+
0 <= N <= 10
39+
40+
递归。
41+
*/
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
public class Solution3538 {
2+
private int[] position;
3+
private int[] s;
4+
private int[][][] memo;
5+
6+
public int minTravelTime(int l, int n, int k, int[] position, int[] time) {
7+
this.position = position;
8+
s = new int[n];
9+
for (int i = 0; i < n - 1; i++) { // time[n-1] 用不到
10+
s[i + 1] = s[i] + time[i]; // 计算 time 的前缀和
11+
}
12+
13+
memo = new int[n - 1][n - 1][k + 1];
14+
return dfs(0, 0, k); // 第一个子数组是 [0, 0]
15+
}
16+
17+
private int dfs(int i, int j, int leftK) {
18+
int n = position.length;
19+
if (j == n - 1) { // 到达终点
20+
return leftK > 0 ? Integer.MAX_VALUE / 2 : 0; // 除以 2,避免下面计算 r 的地方加法溢出
21+
}
22+
if (memo[i][j][leftK] > 0) { // 之前计算过
23+
return memo[i][j][leftK];
24+
}
25+
int res = Integer.MAX_VALUE;
26+
int t = s[j + 1] - s[i]; // 合并到 time[j] 的时间
27+
// 枚举下一个子数组 [j+1, k]
28+
for (int k = j + 1; k < Math.min(n, j + 2 + leftK); k++) {
29+
int r = dfs(j + 1, k, leftK - (k - j - 1)) + (position[k] - position[j]) * t;
30+
res = Math.min(res, r);
31+
}
32+
return memo[i][j][leftK] = res; // 记忆化
33+
}
34+
}
35+
/*
36+
3538. 合并得到最小旅行时间
37+
https://leetcode.cn/problems/merge-operations-for-minimum-travel-time/description/
38+
39+
第 448 场周赛 T3。
40+
41+
给你一个长度为 l 公里的直路,一个整数 n,一个整数 k 和 两个 长度为 n 的整数数组 position 和 time 。
42+
数组 position 列出了路标的位置(单位:公里),并且是 严格 升序排列的(其中 position[0] = 0 且 position[n - 1] = l)。
43+
每个 time[i] 表示从 position[i] 到 position[i + 1] 之间行驶 1 公里所需的时间(单位:分钟)。
44+
你 必须 执行 恰好 k 次合并操作。在一次合并中,你可以选择两个相邻的路标,下标为 i 和 i + 1(其中 i > 0 且 i + 1 < n),并且:
45+
- 更新索引为 i + 1 的路标,使其时间变为 time[i] + time[i + 1]。
46+
- 删除索引为 i 的路标。
47+
返回经过 恰好 k 次合并后从 0 到 l 的 最小总旅行时间(单位:分钟)。
48+
提示:
49+
1 <= l <= 10^5
50+
2 <= n <= min(l + 1, 50)
51+
0 <= k <= min(n - 2, 10)
52+
position.length == n
53+
position[0] = 0 和 position[n - 1] = l
54+
position 是严格升序排列的。
55+
time.length == n
56+
1 <= time[i] <= 100
57+
1 <= sum(time) <= 100
58+
59+
相邻相关划分型 DP
60+
https://leetcode.cn/problems/merge-operations-for-minimum-travel-time/solutions/3668454/hua-fen-xing-dpcong-ji-yi-hua-sou-suo-da-cref/
61+
时间复杂度 O(n * k^3)
62+
rating 2453 (clist.by)
63+
*/
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3539 {
4+
private int[][] powV;
5+
private int[][][][] memo;
6+
7+
public int magicalSum(int m, int k, int[] nums) {
8+
int n = nums.length;
9+
powV = new int[n][m + 1];
10+
for (int i = 0; i < n; i++) {
11+
powV[i][0] = 1;
12+
for (int j = 1; j <= m; j++) {
13+
powV[i][j] = (int) ((long) powV[i][j - 1] * nums[i] % MOD);
14+
}
15+
}
16+
17+
memo = new int[n][m + 1][m / 2 + 1][k + 1];
18+
for (int[][][] a : memo) {
19+
for (int[][] b : a) {
20+
for (int[] c : b) {
21+
Arrays.fill(c, -1);
22+
}
23+
}
24+
}
25+
return (int) (dfs(0, m, 0, k) * F[m] % MOD);
26+
}
27+
28+
private long dfs(int i, int leftM, int x, int leftK) {
29+
int c1 = Integer.bitCount(x);
30+
if (c1 + leftM < leftK) { // 可行性剪枝
31+
return 0;
32+
}
33+
if (i == powV.length || leftM == 0 || leftK == 0) { // 无法继续选数字
34+
return leftM == 0 && c1 == leftK ? 1 : 0;
35+
}
36+
if (memo[i][leftM][x][leftK] != -1) {
37+
return memo[i][leftM][x][leftK];
38+
}
39+
long res = 0;
40+
for (int j = 0; j <= leftM; j++) { // 枚举 I 中有 j 个下标 i
41+
// 这 j 个下标 i 对 S 的贡献是 j * pow(2, i)
42+
// 由于 x = S >> i,转化成对 x 的贡献是 j
43+
int bit = (x + j) & 1; // 取最低位,提前从 leftK 中减去,其余进位到 x 中
44+
long r = dfs(i + 1, leftM - j, (x + j) >> 1, leftK - bit);
45+
res = (res + r * powV[i][j] % MOD * invF[j]) % MOD;
46+
}
47+
return memo[i][leftM][x][leftK] = (int) res;
48+
}
49+
50+
static int MOD = (int) 1e9 + 7, MX = (int) 32;
51+
static long[] F = new long[MX + 1], invF = new long[MX + 1];
52+
53+
static {
54+
F[0] = F[1] = invF[0] = invF[1] = 1;
55+
for (int i = 2; i <= MX; i++) F[i] = F[i - 1] * i % MOD;
56+
invF[MX] = quickPow(F[MX], MOD - 2);
57+
for (int i = MX - 1; i >= 2; i--) invF[i] = invF[i + 1] * (i + 1) % MOD;
58+
}
59+
60+
static long comb(int n, int m) {
61+
return F[n] * invF[n - m] % MOD * invF[m] % MOD;
62+
}
63+
64+
static long quickPow(long a, long b) {
65+
long res = 1L;
66+
while (b > 0) {
67+
if ((b & 1) != 0) res = res * a % MOD;
68+
a = a * a % MOD;
69+
b >>= 1;
70+
}
71+
return res;
72+
}
73+
}
74+
/*
75+
3539. 魔法序列的数组乘积之和
76+
https://leetcode.cn/problems/find-sum-of-array-product-of-magical-sequences/description/
77+
78+
第 448 场周赛 T4。
79+
80+
给你两个整数 M 和 K,和一个整数数组 nums。
81+
- seq 的序列长度为 M。
82+
- 0 <= seq[i] < nums.length
83+
- 2^seq[0] + 2^seq[1] + ... + 2^seq[M - 1] 的 二进制形式 有 K 个 置位。
84+
这个序列的 数组乘积 定义为 prod(seq) = (nums[seq[0]] * nums[seq[1]] * ... * nums[seq[M - 1]])。
85+
返回所有有效 魔法 序列的 数组乘积 的 总和 。
86+
由于答案可能很大,返回结果对 10^9 + 7 取模。
87+
置位 是指一个数字的二进制表示中值为 1 的位。
88+
提示:
89+
1 <= K <= M <= 30
90+
1 <= nums.length <= 50
91+
1 <= nums[i] <= 10^8
92+
93+
状态设计 + 多重集排列数 + 可行性剪枝
94+
https://leetcode.cn/problems/find-sum-of-array-product-of-magical-sequences/solutions/3668501/duo-wei-dp-zu-he-shu-xue-by-endlesscheng-j6y8/
95+
时间复杂度 O(n * m^3 * k)
96+
rating 2693 (clist.by)
97+
*/
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3536Tests {
5+
private final Solution3536 solution3536 = new Solution3536();
6+
7+
@Test
8+
public void example1() {
9+
int n = 31;
10+
int expected = 3;
11+
Assertions.assertEquals(expected, solution3536.maxProduct(n));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
int n = 22;
17+
int expected = 4;
18+
Assertions.assertEquals(expected, solution3536.maxProduct(n));
19+
}
20+
21+
@Test
22+
public void example3() {
23+
int n = 124;
24+
int expected = 8;
25+
Assertions.assertEquals(expected, solution3536.maxProduct(n));
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3537Tests {
5+
private final Solution3537 solution3537 = new Solution3537();
6+
7+
@Test
8+
public void example1() {
9+
int n = 0;
10+
int[][] expected = UtUtils.stringToInts2("[[0]]");
11+
Assertions.assertArrayEquals(expected, solution3537.specialGrid(n));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
int n = 1;
17+
int[][] expected = UtUtils.stringToInts2("[[3,0],[2,1]]");
18+
Assertions.assertArrayEquals(expected, solution3537.specialGrid(n));
19+
}
20+
21+
@Test
22+
public void example3() {
23+
int n = 2;
24+
int[][] expected = UtUtils.stringToInts2("[[15,12,3,0],[14,13,2,1],[11,8,7,4],[10,9,6,5]]");
25+
Assertions.assertArrayEquals(expected, solution3537.specialGrid(n));
26+
}
27+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3538Tests {
5+
private final Solution3538 solution3538 = new Solution3538();
6+
7+
@Test
8+
public void example1() {
9+
int l = 10;
10+
int n = 4;
11+
int k = 1;
12+
int[] position = {0, 3, 8, 10};
13+
int[] time = {5, 8, 3, 6};
14+
int expected = 62;
15+
Assertions.assertEquals(expected, solution3538.minTravelTime(l, n, k, position, time));
16+
}
17+
18+
@Test
19+
public void example2() {
20+
int l = 5;
21+
int n = 5;
22+
int k = 1;
23+
int[] position = {0, 1, 2, 3, 5};
24+
int[] time = {8, 3, 9, 3, 3};
25+
int expected = 34;
26+
Assertions.assertEquals(expected, solution3538.minTravelTime(l, n, k, position, time));
27+
}
28+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3539Tests {
5+
private final Solution3539 solution3539 = new Solution3539();
6+
7+
@Test
8+
public void example1() {
9+
int m = 5;
10+
int k = 5;
11+
int[] nums = {1, 10, 100, 10000, 1000000};
12+
int expected = 991600007;
13+
Assertions.assertEquals(expected, solution3539.magicalSum(m, k, nums));
14+
}
15+
16+
@Test
17+
public void example2() {
18+
int m = 2;
19+
int k = 2;
20+
int[] nums = {5, 4, 3, 2, 1};
21+
int expected = 170;
22+
Assertions.assertEquals(expected, solution3539.magicalSum(m, k, nums));
23+
}
24+
25+
@Test
26+
public void example3() {
27+
int m = 1;
28+
int k = 1;
29+
int[] nums = {28};
30+
int expected = 28;
31+
Assertions.assertEquals(expected, solution3539.magicalSum(m, k, nums));
32+
}
33+
}

0 commit comments

Comments
(0)

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