From b075fa635d0a651306f1d4dcdd6ecc290ce0a53e Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 23 Jul 2024 09:27:29 +0800 Subject: [PATCH 1/3] feat: add solutions to lc problem: No.3098 No.3098.Find the Sum of Subsequence Powers --- .../README.md | 90 +++++++++++++++- .../README_EN.md | 102 ++++++++++++++++-- .../Solution.cpp | 31 ++++++ .../Solution.go | 3 + .../Solution.java | 3 + .../Solution.py | 2 + .../Solution.ts | 36 +++++++ 7 files changed, 259 insertions(+), 8 deletions(-) create mode 100644 solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.cpp create mode 100644 solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.ts diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md index d6035ffb395cc..557db81e3e665 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md @@ -84,11 +84,14 @@ tags: ### 方法一:记忆化搜索 -我们设计一个函数 $dfs(i, j, k, mi)$,表示当前处理到第 $i$ 个元素,上一个选取的是第 $j$ 个元素,还需要选取 $k$ 个元素,当前的最小差值为 $mi$ 时,能量和的值。那么答案就是 $dfs(0, n, k, +\infty)$。 +由于题目涉及子序列元素的最小差值,我们不妨对数组 $\textit{nums}$ 进行排序,这样可以方便我们计算子序列元素的最小差值。 + +接下来,我们设计一个函数 $dfs(i, j, k, mi)$,表示当前处理到第 $i$ 个元素,上一个选取的是第 $j$ 个元素,还需要选取 $k$ 个元素,当前的最小差值为 $mi$ 时,能量和的值。那么答案就是 $dfs(0, n, k, +\infty)$。(若上一个选取的是第 $n$ 个元素,表示之前没有选取过元素) 函数 $dfs(i, j, k, mi)$ 的执行过程如下: - 如果 $i \geq n$,表示已经处理完了所有的元素,如果 $k = 0$,返回 $mi$,否则返回 $0$; +- 如果剩余的元素格式 $n - i$ 不足 $k$ 个,返回 $0$; - 否则,我们可以选择不选取第 $i$ 个元素,可以获得的能量和为 $dfs(i + 1, j, k, mi)$; - 也可以选择选取第 $i$ 个元素。如果 $j = n$,表示之前没有选取过元素,那么可以获得的能量和为 $dfs(i + 1, i, k - 1, mi)$;否则,可以获得的能量和为 $dfs(i + 1, i, k - 1, \min(mi, \text{nums}[i] - \text{nums}[j]))$。 - 我们累加上述结果,并对 $10^9 + 7$ 取模后返回。 @@ -108,6 +111,8 @@ class Solution: def dfs(i: int, j: int, k: int, mi: int) -> int: if i >= n: return mi if k == 0 else 0 + if n - i < k: + return 0 ans = dfs(i + 1, j, k, mi) if j == n: ans += dfs(i + 1, i, k - 1, mi) @@ -140,6 +145,9 @@ class Solution { if (i >= nums.length) { return k == 0 ? mi : 0; } + if (nums.length - i < k) { + return 0; + } long key = (1L * mi) << 18 | (i << 12) | (j << 6) | k; if (f.containsKey(key)) { return f.get(key); @@ -157,6 +165,42 @@ class Solution { } ``` +#### C++ + +```cpp +class Solution { +public: + int sumOfPowers(vector& nums, int k) { + unordered_map f; + const int mod = 1e9 + 7; + int n = nums.size(); + sort(nums.begin(), nums.end()); + auto dfs = [&](auto&& dfs, int i, int j, int k, int mi) -> int { + if (i >= n) { + return k == 0 ? mi : 0; + } + if (n - i < k) { + return 0; + } + long long key = (1LL * mi) << 18 | (i << 12) | (j << 6) | k; + if (f.contains(key)) { + return f[key]; + } + long long ans = dfs(dfs, i + 1, j, k, mi); + if (j == n) { + ans += dfs(dfs, i + 1, i, k - 1, mi); + } else { + ans += dfs(dfs, i + 1, i, k - 1, min(mi, nums[i] - nums[j])); + } + ans %= mod; + f[key] = ans; + return f[key]; + }; + return dfs(dfs, 0, n, k, INT_MAX); + } +}; +``` + #### Go ```go @@ -173,6 +217,9 @@ func sumOfPowers(nums []int, k int) int { } return 0 } + if n-i < k { + return 0 + } key := mi<<18 | (i << 12) | (j << 6) | k if v, ok := f[key]; ok { return v @@ -191,6 +238,47 @@ func sumOfPowers(nums []int, k int) int { } ``` +#### TypeScript + +```ts +function sumOfPowers(nums: number[], k: number): number { + const mod = BigInt(1e9 + 7); + nums.sort((a, b) => a - b); + const n = nums.length; + const f: Map = new Map(); + function dfs(i: number, j: number, k: number, mi: number): bigint { + if (i >= n) { + if (k === 0) { + return BigInt(mi); + } + return BigInt(0); + } + if (n - i < k) { + return BigInt(0); + } + const key = + (BigInt(mi) << BigInt(18)) | + (BigInt(i) << BigInt(12)) | + (BigInt(j) << BigInt(6)) | + BigInt(k); + if (f.has(key)) { + return f.get(key)!; + } + let ans = dfs(i + 1, j, k, mi); + if (j === n) { + ans += dfs(i + 1, i, k - 1, mi); + } else { + ans += dfs(i + 1, i, k - 1, Math.min(mi, nums[i] - nums[j])); + } + ans %= mod; + f.set(key, ans); + return ans; + } + + return Number(dfs(0, n, k, Number.MAX_SAFE_INTEGER)); +} +``` + diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README_EN.md b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README_EN.md index cf67f3a399d49..0196c07020c34 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README_EN.md +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README_EN.md @@ -82,18 +82,21 @@ tags: ### Solution 1: Memoization Search -We design a function $dfs(i, j, k, mi)$, which represents the energy sum value when we are currently processing the $i$-th element, the last selected element is the $j$-th element, we still need to select $k$ elements, and the current minimum difference is $mi$. The answer is $dfs(0, n, k, +\infty)$. +Given the problem involves the minimum difference between elements of a subsequence, we might as well sort the array $\textit{nums}$, which facilitates the calculation of the minimum difference between subsequence elements. + +Next, we design a function $dfs(i, j, k, mi)$, representing the value of the energy sum when processing the $i$-th element, the last selected element is the $j$-th element, $k$ more elements need to be selected, and the current minimum difference is $mi$. Therefore, the answer is $dfs(0, n, k, +\infty)$ (If the last selected element is the $n$-th element, it indicates that no element has been selected before). The execution process of the function $dfs(i, j, k, mi)$ is as follows: -- If $i \geq n$, it means that all elements have been processed. If $k = 0$, return $mi$, otherwise return $0$; -- Otherwise, we can choose not to select the $i$-th element, and the energy sum obtained is $dfs(i + 1, j, k, mi)$; -- We can also choose to select the $i$-th element. If $j = n$, it means that no element has been selected before, and the energy sum obtained is $dfs(i + 1, i, k - 1, mi)$; otherwise, the energy sum obtained is $dfs(i + 1, i, k - 1, \min(mi, \text{nums}[i] - \text{nums}[j]))$. -- We add up the above results, take the modulus of $10^9 + 7$, and return. +- If $i \geq n$, it means all elements have been processed. If $k = 0$, return $mi$; otherwise, return $0$. +- If the remaining number of elements $n - i$ is less than $k$, return $0$. +- Otherwise, we can choose not to select the $i$-th element, and the energy sum obtained is $dfs(i + 1, j, k, mi)$. +- We can also choose to select the $i$-th element. If $j = n$, it means no element has been selected before, then the energy sum obtained is $dfs(i + 1, i, k - 1, mi)$; otherwise, the energy sum obtained is $dfs(i + 1, i, k - 1, \min(mi, \text{nums}[i] - \text{nums}[j]))$. +- We add up the above results and return the result modulo $10^9 + 7$. -To avoid repeated calculations, we can use the method of memoization search to save the calculated results. +To avoid repeated calculations, we can use memoization, saving the results that have already been calculated. -The time complexity is $O(n^4 \times k)$, and the space complexity is $O(n^4 \times k)$. Where $n$ is the length of the array. +The time complexity is $O(n^4 \times k)$, and the space complexity is $O(n^4 \times k)$. Here, $n$ is the length of the array. @@ -106,6 +109,8 @@ class Solution: def dfs(i: int, j: int, k: int, mi: int) -> int: if i >= n: return mi if k == 0 else 0 + if n - i < k: + return 0 ans = dfs(i + 1, j, k, mi) if j == n: ans += dfs(i + 1, i, k - 1, mi) @@ -138,6 +143,9 @@ class Solution { if (i >= nums.length) { return k == 0 ? mi : 0; } + if (nums.length - i < k) { + return 0; + } long key = (1L * mi) << 18 | (i << 12) | (j << 6) | k; if (f.containsKey(key)) { return f.get(key); @@ -155,6 +163,42 @@ class Solution { } ``` +#### C++ + +```cpp +class Solution { +public: + int sumOfPowers(vector& nums, int k) { + unordered_map f; + const int mod = 1e9 + 7; + int n = nums.size(); + sort(nums.begin(), nums.end()); + auto dfs = [&](auto&& dfs, int i, int j, int k, int mi) -> int { + if (i >= n) { + return k == 0 ? mi : 0; + } + if (n - i < k) { + return 0; + } + long long key = (1LL * mi) << 18 | (i << 12) | (j << 6) | k; + if (f.contains(key)) { + return f[key]; + } + long long ans = dfs(dfs, i + 1, j, k, mi); + if (j == n) { + ans += dfs(dfs, i + 1, i, k - 1, mi); + } else { + ans += dfs(dfs, i + 1, i, k - 1, min(mi, nums[i] - nums[j])); + } + ans %= mod; + f[key] = ans; + return f[key]; + }; + return dfs(dfs, 0, n, k, INT_MAX); + } +}; +``` + #### Go ```go @@ -171,6 +215,9 @@ func sumOfPowers(nums []int, k int) int { } return 0 } + if n-i < k { + return 0 + } key := mi<<18 | (i << 12) | (j << 6) | k if v, ok := f[key]; ok { return v @@ -189,6 +236,47 @@ func sumOfPowers(nums []int, k int) int { } ``` +#### TypeScript + +```ts +function sumOfPowers(nums: number[], k: number): number { + const mod = BigInt(1e9 + 7); + nums.sort((a, b) => a - b); + const n = nums.length; + const f: Map = new Map(); + function dfs(i: number, j: number, k: number, mi: number): bigint { + if (i >= n) { + if (k === 0) { + return BigInt(mi); + } + return BigInt(0); + } + if (n - i < k) { + return BigInt(0); + } + const key = + (BigInt(mi) << BigInt(18)) | + (BigInt(i) << BigInt(12)) | + (BigInt(j) << BigInt(6)) | + BigInt(k); + if (f.has(key)) { + return f.get(key)!; + } + let ans = dfs(i + 1, j, k, mi); + if (j === n) { + ans += dfs(i + 1, i, k - 1, mi); + } else { + ans += dfs(i + 1, i, k - 1, Math.min(mi, nums[i] - nums[j])); + } + ans %= mod; + f.set(key, ans); + return ans; + } + + return Number(dfs(0, n, k, Number.MAX_SAFE_INTEGER)); +} +``` + diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.cpp b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.cpp new file mode 100644 index 0000000000000..7e5407b6435b3 --- /dev/null +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.cpp @@ -0,0 +1,31 @@ +class Solution { +public: + int sumOfPowers(vector& nums, int k) { + unordered_map f; + const int mod = 1e9 + 7; + int n = nums.size(); + sort(nums.begin(), nums.end()); + auto dfs = [&](auto&& dfs, int i, int j, int k, int mi) -> int { + if (i >= n) { + return k == 0 ? mi : 0; + } + if (n - i < k) { + return 0; + } + long long key = (1LL * mi) << 18 | (i << 12) | (j << 6) | k; + if (f.contains(key)) { + return f[key]; + } + long long ans = dfs(dfs, i + 1, j, k, mi); + if (j == n) { + ans += dfs(dfs, i + 1, i, k - 1, mi); + } else { + ans += dfs(dfs, i + 1, i, k - 1, min(mi, nums[i] - nums[j])); + } + ans %= mod; + f[key] = ans; + return f[key]; + }; + return dfs(dfs, 0, n, k, INT_MAX); + } +}; \ No newline at end of file diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.go b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.go index 75b1528dde09e..644ad8377e227 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.go +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.go @@ -11,6 +11,9 @@ func sumOfPowers(nums []int, k int) int { } return 0 } + if n-i < k { + return 0 + } key := mi<<18 | (i << 12) | (j << 6) | k if v, ok := f[key]; ok { return v diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.java b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.java index ee6e753cf1ada..ed981e0a2aba5 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.java +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.java @@ -13,6 +13,9 @@ private int dfs(int i, int j, int k, int mi) { if (i >= nums.length) { return k == 0 ? mi : 0; } + if (nums.length - i < k) { + return 0; + } long key = (1L * mi) << 18 | (i << 12) | (j << 6) | k; if (f.containsKey(key)) { return f.get(key); diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.py b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.py index 89d6cc5d3688e..f570a54adb8d9 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.py +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.py @@ -4,6 +4,8 @@ def sumOfPowers(self, nums: List[int], k: int) -> int: def dfs(i: int, j: int, k: int, mi: int) -> int: if i >= n: return mi if k == 0 else 0 + if n - i < k: + return 0 ans = dfs(i + 1, j, k, mi) if j == n: ans += dfs(i + 1, i, k - 1, mi) diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.ts b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.ts new file mode 100644 index 0000000000000..53b27d04f4109 --- /dev/null +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/Solution.ts @@ -0,0 +1,36 @@ +function sumOfPowers(nums: number[], k: number): number { + const mod = BigInt(1e9 + 7); + nums.sort((a, b) => a - b); + const n = nums.length; + const f: Map = new Map(); + function dfs(i: number, j: number, k: number, mi: number): bigint { + if (i >= n) { + if (k === 0) { + return BigInt(mi); + } + return BigInt(0); + } + if (n - i < k) { + return BigInt(0); + } + const key = + (BigInt(mi) << BigInt(18)) | + (BigInt(i) << BigInt(12)) | + (BigInt(j) << BigInt(6)) | + BigInt(k); + if (f.has(key)) { + return f.get(key)!; + } + let ans = dfs(i + 1, j, k, mi); + if (j === n) { + ans += dfs(i + 1, i, k - 1, mi); + } else { + ans += dfs(i + 1, i, k - 1, Math.min(mi, nums[i] - nums[j])); + } + ans %= mod; + f.set(key, ans); + return ans; + } + + return Number(dfs(0, n, k, Number.MAX_SAFE_INTEGER)); +} From 354aacb43f73cfb7a8a7f78dc621cc3e852cfd76 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 23 Jul 2024 09:35:01 +0800 Subject: [PATCH 2/3] fix: update --- .../3000-3099/3098.Find the Sum of Subsequence Powers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md index 557db81e3e665..e585448d802ce 100644 --- a/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md +++ b/solution/3000-3099/3098.Find the Sum of Subsequence Powers/README.md @@ -91,7 +91,7 @@ tags: 函数 $dfs(i, j, k, mi)$ 的执行过程如下: - 如果 $i \geq n$,表示已经处理完了所有的元素,如果 $k = 0$,返回 $mi$,否则返回 $0$; -- 如果剩余的元素格式 $n - i$ 不足 $k$ 个,返回 $0$; +- 如果剩余的元素个数 $n - i$ 不足 $k$ 个,返回 $0$; - 否则,我们可以选择不选取第 $i$ 个元素,可以获得的能量和为 $dfs(i + 1, j, k, mi)$; - 也可以选择选取第 $i$ 个元素。如果 $j = n$,表示之前没有选取过元素,那么可以获得的能量和为 $dfs(i + 1, i, k - 1, mi)$;否则,可以获得的能量和为 $dfs(i + 1, i, k - 1, \min(mi, \text{nums}[i] - \text{nums}[j]))$。 - 我们累加上述结果,并对 $10^9 + 7$ 取模后返回。 From b8c1fb9eb788ac3e32269bdaa72861f03bf5d32c Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 23 Jul 2024 09:38:16 +0800 Subject: [PATCH 3/3] fix: update --- .../README.md | 8 ++++---- .../README_EN.md | 8 ++++---- .../Solution.cpp | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README.md b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README.md index 3634817955d0a..7b1fa3d3b7bae 100644 --- a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README.md +++ b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README.md @@ -144,18 +144,18 @@ public: int n = num.size(); int f[n][25]; memset(f, -1, sizeof(f)); - function dfs = [&](int i, int k) -> int { + auto dfs = [&](auto&& dfs, int i, int k) -> int { if (i == n) { return k == 0 ? 0 : n; } if (f[i][k] != -1) { return f[i][k]; } - f[i][k] = dfs(i + 1, k) + 1; - f[i][k] = min(f[i][k], dfs(i + 1, (k * 10 + num[i] - '0') % 25)); + f[i][k] = dfs(dfs, i + 1, k) + 1; + f[i][k] = min(f[i][k], dfs(dfs, i + 1, (k * 10 + num[i] - '0') % 25)); return f[i][k]; }; - return dfs(0, 0); + return dfs(dfs, 0, 0); } }; ``` diff --git a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README_EN.md b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README_EN.md index de2bc8aaa4061..6308ad3d9db7c 100644 --- a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README_EN.md +++ b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/README_EN.md @@ -141,18 +141,18 @@ public: int n = num.size(); int f[n][25]; memset(f, -1, sizeof(f)); - function dfs = [&](int i, int k) -> int { + auto dfs = [&](auto&& dfs, int i, int k) -> int { if (i == n) { return k == 0 ? 0 : n; } if (f[i][k] != -1) { return f[i][k]; } - f[i][k] = dfs(i + 1, k) + 1; - f[i][k] = min(f[i][k], dfs(i + 1, (k * 10 + num[i] - '0') % 25)); + f[i][k] = dfs(dfs, i + 1, k) + 1; + f[i][k] = min(f[i][k], dfs(dfs, i + 1, (k * 10 + num[i] - '0') % 25)); return f[i][k]; }; - return dfs(0, 0); + return dfs(dfs, 0, 0); } }; ``` diff --git a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/Solution.cpp b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/Solution.cpp index 673601a4d7bb8..e8a8ee38b3f0a 100644 --- a/solution/2800-2899/2844.Minimum Operations to Make a Special Number/Solution.cpp +++ b/solution/2800-2899/2844.Minimum Operations to Make a Special Number/Solution.cpp @@ -4,17 +4,17 @@ class Solution { int n = num.size(); int f[n][25]; memset(f, -1, sizeof(f)); - function dfs = [&](int i, int k) -> int { + auto dfs = [&](auto&& dfs, int i, int k) -> int { if (i == n) { return k == 0 ? 0 : n; } if (f[i][k] != -1) { return f[i][k]; } - f[i][k] = dfs(i + 1, k) + 1; - f[i][k] = min(f[i][k], dfs(i + 1, (k * 10 + num[i] - '0') % 25)); + f[i][k] = dfs(dfs, i + 1, k) + 1; + f[i][k] = min(f[i][k], dfs(dfs, i + 1, (k * 10 + num[i] - '0') % 25)); return f[i][k]; }; - return dfs(0, 0); + return dfs(dfs, 0, 0); } }; \ No newline at end of file