diff --git a/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/README.md b/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/README.md index 14351bbdf47ba..11765ee990683 100644 --- a/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/README.md +++ b/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/README.md @@ -60,7 +60,24 @@ tags: -### 方法一 +### 方法一:动态规划 + +我们定义 $f[i][j]$ 表示在前 $i$ 个正整数中选取一些数的 $x$ 次幂之和等于 $j$ 的方案数,初始时 $f[0][0] = 1$,其余均为 $0$。答案为 $f[n][n]$。 + +对于每个正整数 $i$,我们可以选择不选它或者选它: + +- 不选它:此时方案数为 $f[i-1][j]$; +- 选它:此时方案数为 $f[i-1][j-i^x]$(前提是 $j \geq i^x$)。 + +因此状态转移方程为: + +$$ +f[i][j] = f[i-1][j] + (j \geq i^x ? f[i-1][j-i^x] : 0) +$$ + +注意到答案可能非常大,我们需要对 $10^9 + 7$ 取余。 + +时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 是题目中给定的整数。 @@ -155,9 +172,7 @@ func numberOfWays(n int, x int) int { ```ts function numberOfWays(n: number, x: number): number { const mod = 10 ** 9 + 7; - const f: number[][] = Array(n + 1) - .fill(0) - .map(() => Array(n + 1).fill(0)); + const f = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0)); f[0][0] = 1; for (let i = 1; i <= n; ++i) { const k = Math.pow(i, x); @@ -172,6 +187,30 @@ function numberOfWays(n: number, x: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn number_of_ways(n: i32, x: i32) -> i32 { + const MOD: i64 = 1_000_000_007; + let n = n as usize; + let x = x as u32; + let mut f = vec![vec![0; n + 1]; n + 1]; + f[0][0] = 1; + for i in 1..=n { + let k = (i as i64).pow(x); + for j in 0..=n { + f[i][j] = f[i - 1][j]; + if j >= k as usize { + f[i][j] = (f[i][j] + f[i - 1][j - k as usize]) % MOD; + } + } + } + f[n][n] as i32 + } +} +``` + diff --git a/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/README_EN.md b/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/README_EN.md index 7b305c05503a0..f1a00799e35cb 100644 --- a/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/README_EN.md +++ b/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/README_EN.md @@ -60,7 +60,24 @@ It can be shown that it is the only way to express 10 as the sum of the 2nd -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i][j]$ as the number of ways to select some numbers from the first $i$ positive integers such that the sum of their $x$-th powers equals $j$. Initially, $f[0][0] = 1$, and all others are $0$. The answer is $f[n][n]$. + +For each positive integer $i$, we can choose to either include it or not: + +- Not include it: the number of ways is $f[i-1][j]$; +- Include it: the number of ways is $f[i-1][j-i^x]$ (provided that $j \geq i^x$). + +Therefore, the state transition equation is: + +$$ +f[i][j] = f[i-1][j] + (j \geq i^x ? f[i-1][j-i^x] : 0) +$$ + +Note that the answer can be very large, so we need to take modulo $10^9 + 7$. + +The time complexity is $O(n^2)$, and the space complexity is $O(n^2)$, where $n$ is the given integer in the @@ -155,9 +172,7 @@ func numberOfWays(n int, x int) int { ```ts function numberOfWays(n: number, x: number): number { const mod = 10 ** 9 + 7; - const f: number[][] = Array(n + 1) - .fill(0) - .map(() => Array(n + 1).fill(0)); + const f = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0)); f[0][0] = 1; for (let i = 1; i <= n; ++i) { const k = Math.pow(i, x); @@ -172,6 +187,30 @@ function numberOfWays(n: number, x: number): number { } ``` +#### Rust + +```rust +impl Solution { + pub fn number_of_ways(n: i32, x: i32) -> i32 { + const MOD: i64 = 1_000_000_007; + let n = n as usize; + let x = x as u32; + let mut f = vec![vec![0; n + 1]; n + 1]; + f[0][0] = 1; + for i in 1..=n { + let k = (i as i64).pow(x); + for j in 0..=n { + f[i][j] = f[i - 1][j]; + if j >= k as usize { + f[i][j] = (f[i][j] + f[i - 1][j - k as usize]) % MOD; + } + } + } + f[n][n] as i32 + } +} +``` + diff --git a/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/Solution.rs b/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/Solution.rs new file mode 100644 index 0000000000000..018e389b27799 --- /dev/null +++ b/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/Solution.rs @@ -0,0 +1,19 @@ +impl Solution { + pub fn number_of_ways(n: i32, x: i32) -> i32 { + const MOD: i64 = 1_000_000_007; + let n = n as usize; + let x = x as u32; + let mut f = vec![vec![0; n + 1]; n + 1]; + f[0][0] = 1; + for i in 1..=n { + let k = (i as i64).pow(x); + for j in 0..=n { + f[i][j] = f[i - 1][j]; + if j >= k as usize { + f[i][j] = (f[i][j] + f[i - 1][j - k as usize]) % MOD; + } + } + } + f[n][n] as i32 + } +} diff --git a/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/Solution.ts b/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/Solution.ts index 9c7c4bc3290a5..e61b2ac422c08 100644 --- a/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/Solution.ts +++ b/solution/2700-2799/2787.Ways to Express an Integer as Sum of Powers/Solution.ts @@ -1,8 +1,6 @@ function numberOfWays(n: number, x: number): number { const mod = 10 ** 9 + 7; - const f: number[][] = Array(n + 1) - .fill(0) - .map(() => Array(n + 1).fill(0)); + const f = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0)); f[0][0] = 1; for (let i = 1; i <= n; ++i) { const k = Math.pow(i, x); diff --git a/solution/3400-3499/3479.Fruits Into Baskets III/README.md b/solution/3400-3499/3479.Fruits Into Baskets III/README.md index 14098f6839119..c2739bd0faba5 100644 --- a/solution/3400-3499/3479.Fruits Into Baskets III/README.md +++ b/solution/3400-3499/3479.Fruits Into Baskets III/README.md @@ -539,6 +539,158 @@ impl Solution { } ``` +#### C# + +```cs +public class SegmentTree { + int[] nums; + int[] tr; + + public SegmentTree(int[] nums) { + this.nums = nums; + int n = nums.Length; + this.tr = new int[n << 2]; + Build(1, 1, n); + } + + public void Build(int u, int l, int r) { + if (l == r) { + tr[u] = nums[l - 1]; + return; + } + int mid = (l + r) >> 1; + Build(u << 1, l, mid); + Build(u << 1 | 1, mid + 1, r); + Pushup(u); + } + + public void Modify(int u, int l, int r, int i, int v) { + if (l == r) { + tr[u] = v; + return; + } + int mid = (l + r) >> 1; + if (i <= mid) { + Modify(u << 1, l, mid, i, v); + } else { + Modify(u << 1 | 1, mid + 1, r, i, v); + } + Pushup(u); + } + + public int Query(int u, int l, int r, int v) { + if (tr[u] < v) { + return -1; + } + if (l == r) { + return l; + } + int mid = (l + r) >> 1; + if (tr[u << 1] >= v) { + return Query(u << 1, l, mid, v); + } + return Query(u << 1 | 1, mid + 1, r, v); + } + + public void Pushup(int u) { + tr[u] = Math.Max(tr[u << 1], tr[u << 1 | 1]); + } +} + +public class Solution { + public int NumOfUnplacedFruits(int[] fruits, int[] baskets) { + SegmentTree tree = new SegmentTree(baskets); + int n = baskets.Length; + int ans = 0; + foreach (var x in fruits) { + int i = tree.Query(1, 1, n, x); + if (i < 0) { + ans++; + } else { + tree.Modify(1, 1, n, i, 0); + } + } + return ans; + } +} +``` + +#### Swift + +```swift +class SegmentTree { + var nums: [Int] + var tr: [Int] + + init(_ nums: [Int]) { + self.nums = nums + let n = nums.count + self.tr = [Int](repeating: 0, count: n << 2) + build(1, 1, n) + } + + func build(_ u: Int, _ l: Int, _ r: Int) { + if l == r { + tr[u] = nums[l - 1] + return + } + let mid = (l + r) >> 1 + build(u << 1, l, mid) + build(u << 1 | 1, mid + 1, r) + pushup(u) + } + + func modify(_ u: Int, _ l: Int, _ r: Int, _ i: Int, _ v: Int) { + if l == r { + tr[u] = v + return + } + let mid = (l + r) >> 1 + if i <= mid { + modify(u << 1, l, mid, i, v) + } else { + modify(u << 1 | 1, mid + 1, r, i, v) + } + pushup(u) + } + + func query(_ u: Int, _ l: Int, _ r: Int, _ v: Int) -> Int { + if tr[u] < v { + return -1 + } + if l == r { + return l + } + let mid = (l + r) >> 1 + if tr[u << 1] >= v { + return query(u << 1, l, mid, v) + } + return query(u << 1 | 1, mid + 1, r, v) + } + + func pushup(_ u: Int) { + tr[u] = max(tr[u << 1], tr[u << 1 | 1]) + } +} + +class Solution { + func numOfUnplacedFruits(_ fruits: [Int], _ baskets: [Int]) -> Int { + let tree = SegmentTree(baskets) + let n = baskets.count + var ans = 0 + for x in fruits { + let i = tree.query(1, 1, n, x) + if i < 0 { + ans += 1 + } else { + tree.modify(1, 1, n, i, 0) + } + } + return ans + } +} +``` + diff --git a/solution/3400-3499/3479.Fruits Into Baskets III/README_EN.md b/solution/3400-3499/3479.Fruits Into Baskets III/README_EN.md index 982c82e57d515..2e76819f9746a 100644 --- a/solution/3400-3499/3479.Fruits Into Baskets III/README_EN.md +++ b/solution/3400-3499/3479.Fruits Into Baskets III/README_EN.md @@ -536,6 +536,158 @@ impl Solution { } ``` +#### C# + +```cs +public class SegmentTree { + int[] nums; + int[] tr; + + public SegmentTree(int[] nums) { + this.nums = nums; + int n = nums.Length; + this.tr = new int[n << 2]; + Build(1, 1, n); + } + + public void Build(int u, int l, int r) { + if (l == r) { + tr[u] = nums[l - 1]; + return; + } + int mid = (l + r) >> 1; + Build(u << 1, l, mid); + Build(u << 1 | 1, mid + 1, r); + Pushup(u); + } + + public void Modify(int u, int l, int r, int i, int v) { + if (l == r) { + tr[u] = v; + return; + } + int mid = (l + r) >> 1; + if (i <= mid) { + Modify(u << 1, l, mid, i, v); + } else { + Modify(u << 1 | 1, mid + 1, r, i, v); + } + Pushup(u); + } + + public int Query(int u, int l, int r, int v) { + if (tr[u] < v) { + return -1; + } + if (l == r) { + return l; + } + int mid = (l + r) >> 1; + if (tr[u << 1] >= v) { + return Query(u << 1, l, mid, v); + } + return Query(u << 1 | 1, mid + 1, r, v); + } + + public void Pushup(int u) { + tr[u] = Math.Max(tr[u << 1], tr[u << 1 | 1]); + } +} + +public class Solution { + public int NumOfUnplacedFruits(int[] fruits, int[] baskets) { + SegmentTree tree = new SegmentTree(baskets); + int n = baskets.Length; + int ans = 0; + foreach (var x in fruits) { + int i = tree.Query(1, 1, n, x); + if (i < 0) { + ans++; + } else { + tree.Modify(1, 1, n, i, 0); + } + } + return ans; + } +} +``` + +#### Swift + +```swift +class SegmentTree { + var nums: [Int] + var tr: [Int] + + init(_ nums: [Int]) { + self.nums = nums + let n = nums.count + self.tr = [Int](repeating: 0, count: n << 2) + build(1, 1, n) + } + + func build(_ u: Int, _ l: Int, _ r: Int) { + if l == r { + tr[u] = nums[l - 1] + return + } + let mid = (l + r) >> 1 + build(u << 1, l, mid) + build(u << 1 | 1, mid + 1, r) + pushup(u) + } + + func modify(_ u: Int, _ l: Int, _ r: Int, _ i: Int, _ v: Int) { + if l == r { + tr[u] = v + return + } + let mid = (l + r) >> 1 + if i <= mid { + modify(u << 1, l, mid, i, v) + } else { + modify(u << 1 | 1, mid + 1, r, i, v) + } + pushup(u) + } + + func query(_ u: Int, _ l: Int, _ r: Int, _ v: Int) -> Int { + if tr[u] < v { + return -1 + } + if l == r { + return l + } + let mid = (l + r) >> 1 + if tr[u << 1] >= v { + return query(u << 1, l, mid, v) + } + return query(u << 1 | 1, mid + 1, r, v) + } + + func pushup(_ u: Int) { + tr[u] = max(tr[u << 1], tr[u << 1 | 1]) + } +} + +class Solution { + func numOfUnplacedFruits(_ fruits: [Int], _ baskets: [Int]) -> Int { + let tree = SegmentTree(baskets) + let n = baskets.count + var ans = 0 + for x in fruits { + let i = tree.query(1, 1, n, x) + if i < 0 { + ans += 1 + } else { + tree.modify(1, 1, n, i, 0) + } + } + return ans + } +} +``` + diff --git a/solution/3400-3499/3479.Fruits Into Baskets III/Solution.cs b/solution/3400-3499/3479.Fruits Into Baskets III/Solution.cs new file mode 100644 index 0000000000000..e40d4fe86230f --- /dev/null +++ b/solution/3400-3499/3479.Fruits Into Baskets III/Solution.cs @@ -0,0 +1,71 @@ +public class SegmentTree { + int[] nums; + int[] tr; + + public SegmentTree(int[] nums) { + this.nums = nums; + int n = nums.Length; + this.tr = new int[n << 2]; + Build(1, 1, n); + } + + public void Build(int u, int l, int r) { + if (l == r) { + tr[u] = nums[l - 1]; + return; + } + int mid = (l + r) >> 1; + Build(u << 1, l, mid); + Build(u << 1 | 1, mid + 1, r); + Pushup(u); + } + + public void Modify(int u, int l, int r, int i, int v) { + if (l == r) { + tr[u] = v; + return; + } + int mid = (l + r) >> 1; + if (i <= mid) { + Modify(u << 1, l, mid, i, v); + } else { + Modify(u << 1 | 1, mid + 1, r, i, v); + } + Pushup(u); + } + + public int Query(int u, int l, int r, int v) { + if (tr[u] < v) { + return -1; + } + if (l == r) { + return l; + } + int mid = (l + r) >> 1; + if (tr[u << 1] >= v) { + return Query(u << 1, l, mid, v); + } + return Query(u << 1 | 1, mid + 1, r, v); + } + + public void Pushup(int u) { + tr[u] = Math.Max(tr[u << 1], tr[u << 1 | 1]); + } +} + +public class Solution { + public int NumOfUnplacedFruits(int[] fruits, int[] baskets) { + SegmentTree tree = new SegmentTree(baskets); + int n = baskets.Length; + int ans = 0; + foreach (var x in fruits) { + int i = tree.Query(1, 1, n, x); + if (i < 0) { + ans++; + } else { + tree.Modify(1, 1, n, i, 0); + } + } + return ans; + } +} diff --git a/solution/3400-3499/3479.Fruits Into Baskets III/Solution.swift b/solution/3400-3499/3479.Fruits Into Baskets III/Solution.swift new file mode 100644 index 0000000000000..9f80eaa800e58 --- /dev/null +++ b/solution/3400-3499/3479.Fruits Into Baskets III/Solution.swift @@ -0,0 +1,71 @@ +class SegmentTree { + var nums: [Int] + var tr: [Int] + + init(_ nums: [Int]) { + self.nums = nums + let n = nums.count + self.tr = [Int](repeating: 0, count: n << 2) + build(1, 1, n) + } + + func build(_ u: Int, _ l: Int, _ r: Int) { + if l == r { + tr[u] = nums[l - 1] + return + } + let mid = (l + r) >> 1 + build(u << 1, l, mid) + build(u << 1 | 1, mid + 1, r) + pushup(u) + } + + func modify(_ u: Int, _ l: Int, _ r: Int, _ i: Int, _ v: Int) { + if l == r { + tr[u] = v + return + } + let mid = (l + r) >> 1 + if i <= mid { + modify(u << 1, l, mid, i, v) + } else { + modify(u << 1 | 1, mid + 1, r, i, v) + } + pushup(u) + } + + func query(_ u: Int, _ l: Int, _ r: Int, _ v: Int) -> Int { + if tr[u] < v { + return -1 + } + if l == r { + return l + } + let mid = (l + r) >> 1 + if tr[u << 1] >= v { + return query(u << 1, l, mid, v) + } + return query(u << 1 | 1, mid + 1, r, v) + } + + func pushup(_ u: Int) { + tr[u] = max(tr[u << 1], tr[u << 1 | 1]) + } +} + +class Solution { + func numOfUnplacedFruits(_ fruits: [Int], _ baskets: [Int]) -> Int { + let tree = SegmentTree(baskets) + let n = baskets.count + var ans = 0 + for x in fruits { + let i = tree.query(1, 1, n, x) + if i < 0 { + ans += 1 + } else { + tree.modify(1, 1, n, i, 0) + } + } + return ans + } +}