diff --git a/solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README.md b/solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README.md index 00ae26cba1f97..a63a738d8bede 100644 --- a/solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README.md +++ b/solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README.md @@ -84,7 +84,15 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3341.Fi -### 方法一 +### 方法一:Dijkstra 算法 + +我们定义一个二维数组 $\textit{dist}$,其中 $\textit{dist}[i][j]$ 表示从起点到达房间 $(i, j)$ 所需的最少时间。初始时,我们将 $\textit{dist}$ 数组中的所有元素设为无穷大,然后将起点 $(0, 0)$ 的 $\textit{dist}$ 值设为 $0$。 + +我们使用优先队列 $\textit{pq}$ 存储每一个状态,其中每个状态由三个值 $(d, i, j)$ 组成,表示从起点到达房间 $(i, j)$ 所需的时间为 $d$。初始时,我们将起点 $(0, 0, 0)$ 加入到 $\textit{pq}$ 中。 + +在每一次迭代中,我们取出 $\textit{pq}$ 中的队首元素 $(d, i, j)$,如果 $(i, j)$ 是终点,那么我们返回 $d$。如果 $d$ 大于 $\textit{dist}[i][j]$,那么我们跳过这个状态。否则,我们枚举 $(i, j)$ 的四个相邻位置 $(x, y)$,如果 $(x, y)$ 在地图内,那么我们计算从 $(i, j)$ 到 $(x, y)$ 的最终时间 $t = \max(\textit{moveTime}[x][y], \textit{dist}[i][j]) + 1$,如果 $t$ 小于 $\textit{dist}[x][y]$,那么我们更新 $\textit{dist}[x][y]$ 的值,并将 $(t, x, y)$ 加入到 $\textit{pq}$ 中。 + +时间复杂度 $O(n \times m \times \log (n \times m))$,空间复杂度 $O(n \times m)$。其中 $n$ 和 $m$ 分别是地图的行数和列数。 diff --git a/solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README_EN.md b/solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README_EN.md index 3b5ae2d5e923b..2474d0bd796fc 100644 --- a/solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README_EN.md +++ b/solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README_EN.md @@ -81,7 +81,15 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3341.Fi -### Solution 1 +### Solution 1: Dijkstra's Algorithm + +We define a two-dimensional array $\textit{dist}$, where $\textit{dist}[i][j]$ represents the minimum time required to reach room $(i, j)$ from the starting point. Initially, we set all elements in the $\textit{dist}$ array to infinity, and then set the $\textit{dist}$ value of the starting point $(0, 0)$ to $0$. + +We use a priority queue $\textit{pq}$ to store each state, where each state consists of three values $(d, i, j)$, representing the time $d$ required to reach room $(i, j)$ from the starting point. Initially, we add the starting point $(0, 0, 0)$ to $\textit{pq}$. + +In each iteration, we take the front element $(d, i, j)$ from $\textit{pq}$. If $(i, j)$ is the endpoint, we return $d$. If $d$ is greater than $\textit{dist}[i][j]$, we skip this state. Otherwise, we enumerate the four adjacent positions $(x, y)$ of $(i, j)$. If $(x, y)$ is within the map, we calculate the final time $t$ from $(i, j)$ to $(x, y)$ as $t = \max(\textit{moveTime}[x][y], \textit{dist}[i][j]) + 1$. If $t$ is less than $\textit{dist}[x][y]$, we update the value of $\textit{dist}[x][y]$ and add $(t, x, y)$ to $\textit{pq}$. + +The time complexity is $O(n \times m \times \log (n \times m))$, and the space complexity is $O(n \times m)$. Here, $n$ and $m$ are the number of rows and columns of the map, respectively. diff --git a/solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README.md b/solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README.md index 890314278349c..3f9fb6f5ab040 100644 --- a/solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README.md +++ b/solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README.md @@ -85,7 +85,15 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3342.Fi -### 方法一 +### 方法一:Dijkstra 算法 + +我们定义一个二维数组 $\textit{dist}$,其中 $\textit{dist}[i][j]$ 表示从起点到达房间 $(i, j)$ 所需的最少时间。初始时,我们将 $\textit{dist}$ 数组中的所有元素设为无穷大,然后将起点 $(0, 0)$ 的 $\textit{dist}$ 值设为 $0$。 + +我们使用优先队列 $\textit{pq}$ 存储每一个状态,其中每个状态由三个值 $(d, i, j)$ 组成,表示从起点到达房间 $(i, j)$ 所需的时间为 $d$。初始时,我们将起点 $(0, 0, 0)$ 加入到 $\textit{pq}$ 中。 + +在每一次迭代中,我们取出 $\textit{pq}$ 中的队首元素 $(d, i, j)$,如果 $(i, j)$ 是终点,那么我们返回 $d$。如果 $d$ 大于 $\textit{dist}[i][j]$,那么我们跳过这个状态。否则,我们枚举 $(i, j)$ 的四个相邻位置 $(x, y)$,如果 $(x, y)$ 在地图内,那么我们计算从 $(i, j)$ 到 $(x, y)$ 的最终时间 $t = \max(\textit{moveTime}[x][y], \textit{dist}[i][j]) + (i + 2) \bmod 2 + 1$,如果 $t$ 小于 $\textit{dist}[x][y]$,那么我们更新 $\textit{dist}[x][y]$ 的值,并将 $(t, x, y)$ 加入到 $\textit{pq}$ 中。 + +时间复杂度 $O(n \times m \times \log (n \times m))$,空间复杂度 $O(n \times m)$。其中 $n$ 和 $m$ 分别是地图的行数和列数。 diff --git a/solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README_EN.md b/solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README_EN.md index 66a3e883b8d77..6c6a51e01310d 100644 --- a/solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README_EN.md +++ b/solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README_EN.md @@ -82,7 +82,15 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3342.Fi -### Solution 1 +### Solution 1: Dijkstra's Algorithm + +We define a two-dimensional array $\textit{dist}$, where $\textit{dist}[i][j]$ represents the minimum time required to reach room $(i, j)$ from the starting point. Initially, we set all elements in the $\textit{dist}$ array to infinity, and then set the $\textit{dist}$ value of the starting point $(0, 0)$ to $0$. + +We use a priority queue $\textit{pq}$ to store each state, where each state consists of three values $(d, i, j)$, representing the time $d$ required to reach room $(i, j)$ from the starting point. Initially, we add the starting point $(0, 0, 0)$ to $\textit{pq}$. + +In each iteration, we take the front element $(d, i, j)$ from $\textit{pq}$. If $(i, j)$ is the endpoint, we return $d$. If $d$ is greater than $\textit{dist}[i][j]$, we skip this state. Otherwise, we enumerate the four adjacent positions $(x, y)$ of $(i, j)$. If $(x, y)$ is within the map, we calculate the final time $t$ from $(i, j)$ to $(x, y)$ as $t = \max(\textit{moveTime}[x][y], \textit{dist}[i][j]) + (i + j) \bmod 2 + 1$. If $t$ is less than $\textit{dist}[x][y]$, we update the value of $\textit{dist}[x][y]$ and add $(t, x, y)$ to $\textit{pq}$. + +The time complexity is $O(n \times m \times \log (n \times m))$, and the space complexity is $O(n \times m)$. Here, $n$ and $m$ are the number of rows and columns of the map, respectively. diff --git a/solution/3300-3399/3343.Count Number of Balanced Permutations/README.md b/solution/3300-3399/3343.Count Number of Balanced Permutations/README.md index d9fc09aa64104..4496f3905e724 100644 --- a/solution/3300-3399/3343.Count Number of Balanced Permutations/README.md +++ b/solution/3300-3399/3343.Count Number of Balanced Permutations/README.md @@ -85,32 +85,309 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3343.Co -### 方法一 +### 方法一:记忆化搜索 + 组合数学 + +我们首先统计出字符串 $\textit{num}$ 中每个数字出现的次数,记录在数组 $\textit{cnt}$ 中,然后计算出字符串 $\textit{num}$ 的总和 $\textit{s}$。 + +如果 $\textit{s}$ 是奇数,那么 $\textit{num}$ 一定不是平衡的,直接返回 $0$。 + +接下来,我们定义记忆化搜索函数 $\text{dfs}(i, j, a, b)$,其中 $i$ 表示当前要从数字 $i$ 开始填充,而 $j$ 表示奇数位剩余待填的数字之和,而 $a$ 和 $b$ 分别表示奇数位和偶数位剩余待填的数字个数。我们记字符串 $\textit{num}$ 的长度为 $n$,那么答案就是 $\text{dfs}(0, s / 2, n / 2, (n + 1) / 2)$。 + +在 $\text{dfs}(i, j, a, b)$ 函数中,我们首先判断是否已经填充完了所有的数字,如果是的话,此时需要满足 $j = 0$ 且 $a = 0$ 且 $b = 0$,若满足这个条件,说明当前的排列是平衡的,返回 $1$,否则返回 $0$。 + +接下来,我们判断当前奇数位剩余待填的数字个数 $a$ 是否为 $0$ 且 $j > 0$,如果是的话,说明当前的排列不是平衡的,提前返回 $0$。 + +否则,我们可以枚举当前数字分配给奇数位的数字个数 $l$,那么偶数位的数字个数就是 $r = \textit{cnt}[i] - l$,我们需要满足 $0 \leq r \leq b$ 且 $l \times i \leq j$,然后我们计算出当前的方案数 $t = C_a^l \times C_b^r \times \text{dfs}(i + 1, j - l \times i, a - l, b - r)$,最后答案就是所有方案数之和。 + +时间复杂度 $O(|\Sigma| \times n^2 \times (n + |\Sigma|))$,其中 $|\Sigma|$ 表示数字的种类数,本题中 $|\Sigma| = 10$。空间复杂度 $O(n^2 \times |\Sigma|^2)$。 #### Python3 ```python - +class Solution: + def countBalancedPermutations(self, num: str) -> int: + @cache + def dfs(i: int, j: int, a: int, b: int) -> int: + if i > 9: + return (j | a | b) == 0 + if a == 0 and j: + return 0 + ans = 0 + for l in range(min(cnt[i], a) + 1): + r = cnt[i] - l + if 0 <= r <= b and l * i <= j: + t = comb(a, l) * comb(b, r) * dfs(i + 1, j - l * i, a - l, b - r) + ans = (ans + t) % mod + return ans + + nums = list(map(int, num)) + s = sum(nums) + if s % 2: + return 0 + n = len(nums) + mod = 10**9 + 7 + cnt = Counter(nums) + return dfs(0, s // 2, n // 2, (n + 1) // 2) ``` #### Java ```java - +class Solution { + private final int[] cnt = new int[10]; + private final int mod = (int) 1e9 + 7; + private Integer[][][][] f; + private long[][] c; + + public int countBalancedPermutations(String num) { + int s = 0; + for (char c : num.toCharArray()) { + cnt[c - '0']++; + s += c - '0'; + } + if (s % 2 == 1) { + return 0; + } + int n = num.length(); + int m = n / 2 + 1; + f = new Integer[10][s / 2 + 1][m][m + 1]; + c = new long[m + 1][m + 1]; + c[0][0] = 1; + for (int i = 1; i <= m; i++) { + c[i][0] = 1; + for (int j = 1; j <= i; j++) { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; + } + } + return dfs(0, s / 2, n / 2, (n + 1) / 2); + } + + private int dfs(int i, int j, int a, int b) { + if (i > 9) { + return ((j | a | b) == 0) ? 1 : 0; + } + if (a == 0 && j != 0) { + return 0; + } + if (f[i][j][a][b] != null) { + return f[i][j][a][b]; + } + int ans = 0; + for (int l = 0; l <= Math.min(cnt[i], a); ++l) { + int r = cnt[i] - l; + if (r >= 0 && r <= b && l * i <= j) { + int t = (int) (c[a][l] * c[b][r] % mod * dfs(i + 1, j - l * i, a - l, b - r) % mod); + ans = (ans + t) % mod; + } + } + return f[i][j][a][b] = ans; + } +} ``` #### C++ ```cpp - +using ll = long long; +const int MX = 80; +const int MOD = 1e9 + 7; +ll c[MX][MX]; + +auto init = [] { + c[0][0] = 1; + for (int i = 1; i < MX; ++i) { + c[i][0] = 1; + for (int j = 1; j <= i; ++j) { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD; + } + } + return 0; +}(); + +class Solution { +public: + int countBalancedPermutations(string num) { + int cnt[10]{}; + int s = 0; + for (char& c : num) { + ++cnt[c - '0']; + s += c - '0'; + } + if (s % 2) { + return 0; + } + int n = num.size(); + int m = n / 2 + 1; + int f[10][s / 2 + 1][m][m + 1]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int i, int j, int a, int b) -> int { + if (i > 9) { + return ((j | a | b) == 0 ? 1 : 0); + } + if (a == 0 && j) { + return 0; + } + if (f[i][j][a][b] != -1) { + return f[i][j][a][b]; + } + int ans = 0; + for (int l = 0; l <= min(cnt[i], a); ++l) { + int r = cnt[i] - l; + if (r >= 0 && r <= b && l * i <= j) { + int t = c[a][l] * c[b][r] % MOD * dfs(dfs, i + 1, j - l * i, a - l, b - r) % MOD; + ans = (ans + t) % MOD; + } + } + return f[i][j][a][b] = ans; + }; + return dfs(dfs, 0, s / 2, n / 2, (n + 1) / 2); + } +}; ``` #### Go ```go +const ( + MX = 80 + MOD = 1_000_000_007 +) + +var c [MX][MX]int + +func init() { + c[0][0] = 1 + for i := 1; i < MX; i++ { + c[i][0] = 1 + for j := 1; j <= i; j++ { + c[i][j] = (c[i-1][j] + c[i-1][j-1]) % MOD + } + } +} + +func countBalancedPermutations(num string) int { + var cnt [10]int + s := 0 + for _, ch := range num { + cnt[ch-'0']++ + s += int(ch - '0') + } + + if s%2 != 0 { + return 0 + } + + n := len(num) + m := n/2 + 1 + f := make([][][][]int, 10) + for i := range f { + f[i] = make([][][]int, s/2+1) + for j := range f[i] { + f[i][j] = make([][]int, m) + for k := range f[i][j] { + f[i][j][k] = make([]int, m+1) + for l := range f[i][j][k] { + f[i][j][k][l] = -1 + } + } + } + } + + var dfs func(i, j, a, b int) int + dfs = func(i, j, a, b int) int { + if i > 9 { + if j == 0 && a == 0 && b == 0 { + return 1 + } + return 0 + } + if a == 0 && j > 0 { + return 0 + } + if f[i][j][a][b] != -1 { + return f[i][j][a][b] + } + ans := 0 + for l := 0; l <= min(cnt[i], a); l++ { + r := cnt[i] - l + if r >= 0 && r <= b && l*i <= j { + t := c[a][l] * c[b][r] % MOD * dfs(i+1, j-l*i, a-l, b-r) % MOD + ans = (ans + t) % MOD + } + } + f[i][j][a][b] = ans + return ans + } + + return dfs(0, s/2, n/2, (n+1)/2) +} +``` +#### TypeScript + +```ts +const MX = 80; +const MOD = 10 ** 9 + 7; +const c: number[][] = Array.from({ length: MX }, () => Array(MX).fill(0)); +(function init() { + c[0][0] = 1; + for (let i = 1; i < MX; i++) { + c[i][0] = 1; + for (let j = 1; j <= i; j++) { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD; + } + } +})(); + +function countBalancedPermutations(num: string): number { + const cnt = Array(10).fill(0); + let s = 0; + for (const ch of num) { + cnt[+ch]++; + s += +ch; + } + + if (s % 2 !== 0) { + return 0; + } + + const n = num.length; + const m = Math.floor(n / 2) + 1; + const f: Record = {}; + + const dfs = (i: number, j: number, a: number, b: number): number => { + if (i > 9) { + return (j | a | b) === 0 ? 1 : 0; + } + if (a === 0 && j > 0) { + return 0; + } + + const key = `${i},${j},${a},${b}`; + if (key in f) { + return f[key]; + } + + let ans = 0; + for (let l = 0; l <= Math.min(cnt[i], a); l++) { + const r = cnt[i] - l; + if (r >= 0 && r <= b && l * i <= j) { + const t = Number( + (((BigInt(c[a][l]) * BigInt(c[b][r])) % BigInt(MOD)) * + BigInt(dfs(i + 1, j - l * i, a - l, b - r))) % + BigInt(MOD), + ); + ans = (ans + t) % MOD; + } + } + f[key] = ans; + return ans; + }; + + return dfs(0, s / 2, Math.floor(n / 2), Math.floor((n + 1) / 2)); +} ``` diff --git a/solution/3300-3399/3343.Count Number of Balanced Permutations/README_EN.md b/solution/3300-3399/3343.Count Number of Balanced Permutations/README_EN.md index 23be7371e7121..0e6f12e498222 100644 --- a/solution/3300-3399/3343.Count Number of Balanced Permutations/README_EN.md +++ b/solution/3300-3399/3343.Count Number of Balanced Permutations/README_EN.md @@ -82,32 +82,309 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3343.Co -### Solution 1 +### Solution 1: Memoization Search + Combinatorial Mathematics + +First, we count the occurrences of each digit in the string $\textit{num}$ and record them in the array $\textit{cnt}$, then calculate the total sum $\textit{s}$ of the string $\textit{num}$. + +If $\textit{s}$ is odd, then $\textit{num}$ cannot be balanced, so we directly return $0$. + +Next, we define a memoization search function $\text{dfs}(i, j, a, b)$, where $i$ represents the current digit to be filled, $j$ represents the remaining sum of digits to be filled in odd positions, and $a$ and $b$ represent the remaining number of digits to be filled in odd and even positions, respectively. Let $n$ be the length of the string $\textit{num}$, then the answer is $\text{dfs}(0, s / 2, n / 2, (n + 1) / 2)$. + +In the function $\text{dfs}(i, j, a, b)$, we first check if all digits have been filled. If so, we need to ensure that $j = 0$, $a = 0$, and $b = 0$. If these conditions are met, it means the current arrangement is balanced, so we return $1$; otherwise, we return $0$. + +Next, we check if the remaining number of digits to be filled in odd positions $a$ is $0$ and $j > 0$. If so, it means the current arrangement is not balanced, so we return $0$ early. + +Otherwise, we can enumerate the number of current digits assigned to odd positions $l$, and the number of digits assigned to even positions is $r = \textit{cnt}[i] - l$. We need to ensure $0 \leq r \leq b$ and $l \times i \leq j$. Then we calculate the number of current arrangements $t = C_a^l \times C_b^r \times \text{dfs}(i + 1, j - l \times i, a - l, b - r)$. Finally, the answer is the sum of all arrangement counts. + +The time complexity is $O(|\Sigma| \times n^2 \times (n + |\Sigma|))$, where $|\Sigma|$ represents the number of different digits, and in this problem $|\Sigma| = 10$. The space complexity is $O(n^2 \times |\Sigma|^2)$. #### Python3 ```python - +class Solution: + def countBalancedPermutations(self, num: str) -> int: + @cache + def dfs(i: int, j: int, a: int, b: int) -> int: + if i > 9: + return (j | a | b) == 0 + if a == 0 and j: + return 0 + ans = 0 + for l in range(min(cnt[i], a) + 1): + r = cnt[i] - l + if 0 <= r <= b and l * i <= j: + t = comb(a, l) * comb(b, r) * dfs(i + 1, j - l * i, a - l, b - r) + ans = (ans + t) % mod + return ans + + nums = list(map(int, num)) + s = sum(nums) + if s % 2: + return 0 + n = len(nums) + mod = 10**9 + 7 + cnt = Counter(nums) + return dfs(0, s // 2, n // 2, (n + 1) // 2) ``` #### Java ```java - +class Solution { + private final int[] cnt = new int[10]; + private final int mod = (int) 1e9 + 7; + private Integer[][][][] f; + private long[][] c; + + public int countBalancedPermutations(String num) { + int s = 0; + for (char c : num.toCharArray()) { + cnt[c - '0']++; + s += c - '0'; + } + if (s % 2 == 1) { + return 0; + } + int n = num.length(); + int m = n / 2 + 1; + f = new Integer[10][s / 2 + 1][m][m + 1]; + c = new long[m + 1][m + 1]; + c[0][0] = 1; + for (int i = 1; i <= m; i++) { + c[i][0] = 1; + for (int j = 1; j <= i; j++) { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; + } + } + return dfs(0, s / 2, n / 2, (n + 1) / 2); + } + + private int dfs(int i, int j, int a, int b) { + if (i > 9) { + return ((j | a | b) == 0) ? 1 : 0; + } + if (a == 0 && j != 0) { + return 0; + } + if (f[i][j][a][b] != null) { + return f[i][j][a][b]; + } + int ans = 0; + for (int l = 0; l <= Math.min(cnt[i], a); ++l) { + int r = cnt[i] - l; + if (r >= 0 && r <= b && l * i <= j) { + int t = (int) (c[a][l] * c[b][r] % mod * dfs(i + 1, j - l * i, a - l, b - r) % mod); + ans = (ans + t) % mod; + } + } + return f[i][j][a][b] = ans; + } +} ``` #### C++ ```cpp - +using ll = long long; +const int MX = 80; +const int MOD = 1e9 + 7; +ll c[MX][MX]; + +auto init = [] { + c[0][0] = 1; + for (int i = 1; i < MX; ++i) { + c[i][0] = 1; + for (int j = 1; j <= i; ++j) { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD; + } + } + return 0; +}(); + +class Solution { +public: + int countBalancedPermutations(string num) { + int cnt[10]{}; + int s = 0; + for (char& c : num) { + ++cnt[c - '0']; + s += c - '0'; + } + if (s % 2) { + return 0; + } + int n = num.size(); + int m = n / 2 + 1; + int f[10][s / 2 + 1][m][m + 1]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int i, int j, int a, int b) -> int { + if (i > 9) { + return ((j | a | b) == 0 ? 1 : 0); + } + if (a == 0 && j) { + return 0; + } + if (f[i][j][a][b] != -1) { + return f[i][j][a][b]; + } + int ans = 0; + for (int l = 0; l <= min(cnt[i], a); ++l) { + int r = cnt[i] - l; + if (r >= 0 && r <= b && l * i <= j) { + int t = c[a][l] * c[b][r] % MOD * dfs(dfs, i + 1, j - l * i, a - l, b - r) % MOD; + ans = (ans + t) % MOD; + } + } + return f[i][j][a][b] = ans; + }; + return dfs(dfs, 0, s / 2, n / 2, (n + 1) / 2); + } +}; ``` #### Go ```go +const ( + MX = 80 + MOD = 1_000_000_007 +) + +var c [MX][MX]int + +func init() { + c[0][0] = 1 + for i := 1; i < MX; i++ { + c[i][0] = 1 + for j := 1; j <= i; j++ { + c[i][j] = (c[i-1][j] + c[i-1][j-1]) % MOD + } + } +} + +func countBalancedPermutations(num string) int { + var cnt [10]int + s := 0 + for _, ch := range num { + cnt[ch-'0']++ + s += int(ch - '0') + } + + if s%2 != 0 { + return 0 + } + + n := len(num) + m := n/2 + 1 + f := make([][][][]int, 10) + for i := range f { + f[i] = make([][][]int, s/2+1) + for j := range f[i] { + f[i][j] = make([][]int, m) + for k := range f[i][j] { + f[i][j][k] = make([]int, m+1) + for l := range f[i][j][k] { + f[i][j][k][l] = -1 + } + } + } + } + + var dfs func(i, j, a, b int) int + dfs = func(i, j, a, b int) int { + if i > 9 { + if j == 0 && a == 0 && b == 0 { + return 1 + } + return 0 + } + if a == 0 && j > 0 { + return 0 + } + if f[i][j][a][b] != -1 { + return f[i][j][a][b] + } + ans := 0 + for l := 0; l <= min(cnt[i], a); l++ { + r := cnt[i] - l + if r >= 0 && r <= b && l*i <= j { + t := c[a][l] * c[b][r] % MOD * dfs(i+1, j-l*i, a-l, b-r) % MOD + ans = (ans + t) % MOD + } + } + f[i][j][a][b] = ans + return ans + } + + return dfs(0, s/2, n/2, (n+1)/2) +} +``` +#### TypeScript + +```ts +const MX = 80; +const MOD = 10 ** 9 + 7; +const c: number[][] = Array.from({ length: MX }, () => Array(MX).fill(0)); +(function init() { + c[0][0] = 1; + for (let i = 1; i < MX; i++) { + c[i][0] = 1; + for (let j = 1; j <= i; j++) { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD; + } + } +})(); + +function countBalancedPermutations(num: string): number { + const cnt = Array(10).fill(0); + let s = 0; + for (const ch of num) { + cnt[+ch]++; + s += +ch; + } + + if (s % 2 !== 0) { + return 0; + } + + const n = num.length; + const m = Math.floor(n / 2) + 1; + const f: Record = {}; + + const dfs = (i: number, j: number, a: number, b: number): number => { + if (i > 9) { + return (j | a | b) === 0 ? 1 : 0; + } + if (a === 0 && j > 0) { + return 0; + } + + const key = `${i},${j},${a},${b}`; + if (key in f) { + return f[key]; + } + + let ans = 0; + for (let l = 0; l <= Math.min(cnt[i], a); l++) { + const r = cnt[i] - l; + if (r >= 0 && r <= b && l * i <= j) { + const t = Number( + (((BigInt(c[a][l]) * BigInt(c[b][r])) % BigInt(MOD)) * + BigInt(dfs(i + 1, j - l * i, a - l, b - r))) % + BigInt(MOD), + ); + ans = (ans + t) % MOD; + } + } + f[key] = ans; + return ans; + }; + + return dfs(0, s / 2, Math.floor(n / 2), Math.floor((n + 1) / 2)); +} ``` diff --git a/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.cpp b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.cpp new file mode 100644 index 0000000000000..c596d247f6478 --- /dev/null +++ b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.cpp @@ -0,0 +1,55 @@ +using ll = long long; +const int MX = 80; +const int MOD = 1e9 + 7; +ll c[MX][MX]; + +auto init = [] { + c[0][0] = 1; + for (int i = 1; i < MX; ++i) { + c[i][0] = 1; + for (int j = 1; j <= i; ++j) { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD; + } + } + return 0; +}(); + +class Solution { +public: + int countBalancedPermutations(string num) { + int cnt[10]{}; + int s = 0; + for (char& c : num) { + ++cnt[c - '0']; + s += c - '0'; + } + if (s % 2) { + return 0; + } + int n = num.size(); + int m = n / 2 + 1; + int f[10][s / 2 + 1][m][m + 1]; + memset(f, -1, sizeof(f)); + auto dfs = [&](auto&& dfs, int i, int j, int a, int b) -> int { + if (i > 9) { + return ((j | a | b) == 0 ? 1 : 0); + } + if (a == 0 && j) { + return 0; + } + if (f[i][j][a][b] != -1) { + return f[i][j][a][b]; + } + int ans = 0; + for (int l = 0; l <= min(cnt[i], a); ++l) { + int r = cnt[i] - l; + if (r >= 0 && r <= b && l * i <= j) { + int t = c[a][l] * c[b][r] % MOD * dfs(dfs, i + 1, j - l * i, a - l, b - r) % MOD; + ans = (ans + t) % MOD; + } + } + return f[i][j][a][b] = ans; + }; + return dfs(dfs, 0, s / 2, n / 2, (n + 1) / 2); + } +}; diff --git a/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.go b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.go new file mode 100644 index 0000000000000..29b7d6443e570 --- /dev/null +++ b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.go @@ -0,0 +1,73 @@ +const ( + MX = 80 + MOD = 1_000_000_007 +) + +var c [MX][MX]int + +func init() { + c[0][0] = 1 + for i := 1; i < MX; i++ { + c[i][0] = 1 + for j := 1; j <= i; j++ { + c[i][j] = (c[i-1][j] + c[i-1][j-1]) % MOD + } + } +} + +func countBalancedPermutations(num string) int { + var cnt [10]int + s := 0 + for _, ch := range num { + cnt[ch-'0']++ + s += int(ch - '0') + } + + if s%2 != 0 { + return 0 + } + + n := len(num) + m := n/2 + 1 + f := make([][][][]int, 10) + for i := range f { + f[i] = make([][][]int, s/2+1) + for j := range f[i] { + f[i][j] = make([][]int, m) + for k := range f[i][j] { + f[i][j][k] = make([]int, m+1) + for l := range f[i][j][k] { + f[i][j][k][l] = -1 + } + } + } + } + + var dfs func(i, j, a, b int) int + dfs = func(i, j, a, b int) int { + if i > 9 { + if j == 0 && a == 0 && b == 0 { + return 1 + } + return 0 + } + if a == 0 && j > 0 { + return 0 + } + if f[i][j][a][b] != -1 { + return f[i][j][a][b] + } + ans := 0 + for l := 0; l <= min(cnt[i], a); l++ { + r := cnt[i] - l + if r >= 0 && r <= b && l*i <= j { + t := c[a][l] * c[b][r] % MOD * dfs(i+1, j-l*i, a-l, b-r) % MOD + ans = (ans + t) % MOD + } + } + f[i][j][a][b] = ans + return ans + } + + return dfs(0, s/2, n/2, (n+1)/2) +} diff --git a/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.java b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.java new file mode 100644 index 0000000000000..a29e4d6fc7860 --- /dev/null +++ b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.java @@ -0,0 +1,50 @@ +class Solution { + private final int[] cnt = new int[10]; + private final int mod = (int) 1e9 + 7; + private Integer[][][][] f; + private long[][] c; + + public int countBalancedPermutations(String num) { + int s = 0; + for (char c : num.toCharArray()) { + cnt[c - '0']++; + s += c - '0'; + } + if (s % 2 == 1) { + return 0; + } + int n = num.length(); + int m = n / 2 + 1; + f = new Integer[10][s / 2 + 1][m][m + 1]; + c = new long[m + 1][m + 1]; + c[0][0] = 1; + for (int i = 1; i <= m; i++) { + c[i][0] = 1; + for (int j = 1; j <= i; j++) { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; + } + } + return dfs(0, s / 2, n / 2, (n + 1) / 2); + } + + private int dfs(int i, int j, int a, int b) { + if (i > 9) { + return ((j | a | b) == 0) ? 1 : 0; + } + if (a == 0 && j != 0) { + return 0; + } + if (f[i][j][a][b] != null) { + return f[i][j][a][b]; + } + int ans = 0; + for (int l = 0; l <= Math.min(cnt[i], a); ++l) { + int r = cnt[i] - l; + if (r >= 0 && r <= b && l * i <= j) { + int t = (int) (c[a][l] * c[b][r] % mod * dfs(i + 1, j - l * i, a - l, b - r) % mod); + ans = (ans + t) % mod; + } + } + return f[i][j][a][b] = ans; + } +} diff --git a/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.py b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.py new file mode 100644 index 0000000000000..c884666f38909 --- /dev/null +++ b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.py @@ -0,0 +1,24 @@ +class Solution: + def countBalancedPermutations(self, num: str) -> int: + @cache + def dfs(i: int, j: int, a: int, b: int) -> int: + if i > 9: + return (j | a | b) == 0 + if a == 0 and j: + return 0 + ans = 0 + for l in range(min(cnt[i], a) + 1): + r = cnt[i] - l + if 0 <= r <= b and l * i <= j: + t = comb(a, l) * comb(b, r) * dfs(i + 1, j - l * i, a - l, b - r) + ans = (ans + t) % mod + return ans + + nums = list(map(int, num)) + s = sum(nums) + if s % 2: + return 0 + n = len(nums) + mod = 10**9 + 7 + cnt = Counter(nums) + return dfs(0, s // 2, n // 2, (n + 1) // 2) diff --git a/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.ts b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.ts new file mode 100644 index 0000000000000..f2c6680d451e1 --- /dev/null +++ b/solution/3300-3399/3343.Count Number of Balanced Permutations/Solution.ts @@ -0,0 +1,60 @@ +const MX = 80; +const MOD = 10 ** 9 + 7; +const c: number[][] = Array.from({ length: MX }, () => Array(MX).fill(0)); +(function init() { + c[0][0] = 1; + for (let i = 1; i < MX; i++) { + c[i][0] = 1; + for (let j = 1; j <= i; j++) { + c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD; + } + } +})(); + +function countBalancedPermutations(num: string): number { + const cnt = Array(10).fill(0); + let s = 0; + for (const ch of num) { + cnt[+ch]++; + s += +ch; + } + + if (s % 2 !== 0) { + return 0; + } + + const n = num.length; + const m = Math.floor(n / 2) + 1; + const f: Record = {}; + + const dfs = (i: number, j: number, a: number, b: number): number => { + if (i > 9) { + return (j | a | b) === 0 ? 1 : 0; + } + if (a === 0 && j > 0) { + return 0; + } + + const key = `${i},${j},${a},${b}`; + if (key in f) { + return f[key]; + } + + let ans = 0; + for (let l = 0; l <= Math.min(cnt[i], a); l++) { + const r = cnt[i] - l; + if (r >= 0 && r <= b && l * i <= j) { + const t = Number( + (((BigInt(c[a][l]) * BigInt(c[b][r])) % BigInt(MOD)) * + BigInt(dfs(i + 1, j - l * i, a - l, b - r))) % + BigInt(MOD), + ); + ans = (ans + t) % MOD; + } + } + f[key] = ans; + return ans; + }; + + return dfs(0, s / 2, Math.floor(n / 2), Math.floor((n + 1) / 2)); +}