From 257869c869199648add0adb3f84bad0c69aca62a Mon Sep 17 00:00:00 2001 From: binacs Date: Sat, 16 Dec 2023 10:26:45 +0800 Subject: [PATCH] add: contest weekly 375 --- math/combinatorics/combination.md | 120 ++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/math/combinatorics/combination.md b/math/combinatorics/combination.md index 2505c68..02654b7 100644 --- a/math/combinatorics/combination.md +++ b/math/combinatorics/combination.md @@ -1879,6 +1879,126 @@ public: * * * +> [!NOTE] **[LeetCode 2963. 统计好分割方案的数目](https://leetcode.cn/problems/count-the-number-of-good-partitions/)** +> +> 题意: TODO + +> [!TIP] **思路** +> +> 区间合并 + 组合数 (后者也可转化成 $2^{m-1}$ 思考) + +
+详细代码 + + +##### **C++** + +```cpp +using LL = long long; +const static int N = 1e5 + 10, MOD = 1e9 + 7; + +int qmi(int a, int k, int p) { + int ret = 1; + while (k) { + if (k & 1) + ret = (LL)ret * a % p; + a = (LL)a * a % p; + k >>= 1; + } + return ret; +} + +int fact[N], infact[N]; +bool inited = false; + +void init() { + if (inited) + return; + inited = true; + + fact[0] = infact[0] = 1; + for (int i = 1; i < N; ++ i ) { + fact[i] = (LL)fact[i - 1] * i % MOD; + infact[i] = (LL)infact[i - 1] * qmi(i, MOD - 2, MOD) % MOD; + } +} + +int comb(int a, int b) { + return (LL)fact[a] * infact[b] % MOD * infact[a - b] % MOD; +} + +class Solution { +public: + using PII = pair; + + void merge(vector & segs) { + vector res; + sort(segs.begin(), segs.end()); + int st = -2e9, ed = -2e9; + for (auto seg : segs) + if (ed < seg.first) { + if (st != -2e9) + res.push_back({st, ed}); + st = seg.first, ed = seg.second; + } else + ed = max(ed, seg.second); + if (st != -2e9) + res.push_back({st, ed}); + segs = res; + } + + int numberOfGoodPartitions(vector& nums) { + init(); + + int n = nums.size(); + + unordered_set S; + unordered_map l, r; + { + // 先找到 最左侧/最右侧 出现的位置 + for (int i = 0; i < n; ++ i ) { + int x = nums[i]; + if (S.count(x)) { + l[x] = min(l[x], i), r[x] = max(r[x], i); + } else { + l[x] = r[x] = i; + S.insert(x); + } + } + } + vector xs; + { + // 根据出现过的元素划分基本区间 + for (auto [k, v] : l) + xs.push_back({v, r[k]}); + // 区间合并 + merge(xs); + } + + // 留下的都是可以任意合并的区间 + // 最坏情况下 m=1e5 + int m = xs.size(), res = 0; + for (int i = 0; i < m; ++ i ) + // C{m-1}{i} + res = (res + comb(m - 1, i)) % MOD; + return res; + } +}; +``` + +##### **Python** + +```python + +``` + + +
+ +
+ +* * * + ### 排列数 > [!NOTE] **[AcWing 1309. 车的放置](https://www.acwing.com/problem/content/1311/)** [TAG]