2025.02.27 CW 模拟赛 A. 麻将
A. 麻将
怎么回事呢? 还是太浮躁了吗?
题面
给定 $ n $, $ m $ 和长度为 $ n $ 的序列 $ a $, 保证 $ n $ 为 3 的倍数, 且 $ a_{i} \in [1, m] $.
一个可重三元集合被称为面子, 当且仅当其为形如 $ \{x, x, x\} $ 或 $ \{x, x+1, x+2\} $ 的集合.
试将这 $ n $ 个元素划分为 $ \frac{n}{3} $ 个面子, 输出方案数对 100000007 取模后的结果.
两种划分方案不同, 当且仅当存在一种面子, 在两个划分方案中出现次数不同.
思路
考虑一个 DP: \(f_{i, j, k}\) 表示到第 \(i\) 个数还剩下 \(j\) 个且第 \(i - 1\) 个数剩下 \(k\) 个的方案数. 答案即为 \(f_{m, 0, 0}\).
怎么转移呢? 可以发现, 如果第 \(i - 2\) 个不被用完, 那么这个方案就一定不合法了, 于是我们考虑枚举第 \(i\) 个数合成了 \(l\) 个形如 \(\{ x, x, x \}\) 的面子, 就有
\[f_{i, j, k} = \sum_{l = 0}^{\lfloor \frac{cnt_i - j}{3} \rfloor} f_{i - 1, k + cnt_i - j - 3 \times l, cnt_i - j - 3 \times l}
\]
其中 \(cnt_i\) 指的是 \(i\) 这个数出现了多少次. 同时在转移的时候还需要满足当前状态合法. \((\)即 \(k + cnt_i - j - 3\) 不能大于 \(\max(cnt_{i - 1}, cnt_{i - 2})\), 否则直接 break
掉即可\()\)
在实现时需要使用滚动数组, 清空时要注意范围.
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
using namespace std;
constexpr int N = 2e3 + 1, mod = 1e9 + 7;
int n, m, t[N], f[2][N][N];
void addon(int &x, int y) { if ((x += y) >= mod) x -= mod; }
int max(int x, int y) { return x <= y ? y : x; }
void init() {
scanf("%d %d", &n, &m);
for (int i = 1, x; i <= n; ++i)
scanf("%d", &x), ++t[x];
}
void calculate() {
f[0][0][0] = 1;
for (int i = 1; i <= m; ++i) {
for (int j = 0, _ = max(t[i], i > 1 ? t[i - 2] : 0); j <= _; ++j)
for (int k = 0, __ = max(t[i - 1], i > 2 ? t[i - 3] : 0); k <= __; ++k) f[i & 1][j][k] = 0;
for (int j = 0; j <= t[i]; ++j)
for (int k = 0; k <= t[i - 1]; ++k) {
for (int l = (t[i] - j) / 3; ~l; --l) {
if (k + t[i] - j - 3 * l > (i > 1 ? max(t[i - 1], t[i - 2]) : t[i - 1])) break;
addon(f[i & 1][j][k], f[!(i & 1)][k + t[i] - j - 3 * l][t[i] - j - 3 * l]);
}
}
}
printf("%d", f[m & 1][0][0]);
}
void solve() {
init();
calculate();
}
int main() {
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步