专栏文章

题解:AT_mujin_pc_2018_f チーム分け

AT_mujin_pc_2018_f题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minil301
此快照首次捕获于
2025/12/02 03:00
3 个月前
此快照最后确认于
2025/12/02 03:00
3 个月前
查看原文
神秘题目被神秘搬题人搬到 NOIP 模拟赛 T1。(所以模拟赛成了全原题模拟赛,难度:紫紫紫紫)
以为是签到题,做了 1h 30min 还是只会枚举。
可以考虑设计状态 f(i,j)f(i, j) 表示当前考虑了所有 akia_k \ge i 的人,其中 jj 人还未被匹配的方案数。
c(i)c(i) 为所有 akia_k \ge i 的人的数量。
转移:考虑枚举 kk(当前新组成多少个人数为 ii 的组),然后考虑转移的系数,很显然要首先从 j+c(i)j + c(i) 中选出 kiki 个人,然后排列这 kiki 个人成 kk 组,但是会算重组内的排列和组间的排列方案数也就是 (i!)kk!(i!)^k k!
f(i,j+c(i)ki)f(i+1,j)×(j+c(i)ki)(ki)!(i!)kk!f(i, j + c(i) - ki) \longleftarrow f(i + 1, j) \times \displaystyle\binom{j + c(i)}{ki} \frac{(ki)!}{(i!)^k k!}
注:转移可以化简为
f(i,j+c(i)ki)f(i+1,j)×j+c(i)(j+c(i)ki)!(i!)kk!f(i, j + c(i) - ki) \longleftarrow f(i + 1, j) \times \displaystyle \frac{j + c(i)}{(j + c(i) - ki)!(i!)^k k!}
Code\large{\mathbf{Code}}CPP
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e3 + 10, mod = 998244353;
int n, x, cnt[N], f[N][N], fact[N], infact[N];
int qmi(int a, int k) {
	int res = 1;
	while(k) {
		if(k & 1) res = (LL)res * a % mod;
		a = (LL)a * a % mod;
		k >>= 1;
	}
	return res;
}
int main()
{
	scanf("%d", &n);
	fact[0] = infact[0] = 1;
	for(int i = 1; i <= n; i ++) {
		fact[i] = (LL)fact[i - 1] * i % mod;
		infact[i] = qmi(fact[i], mod - 2);
	}
	for(int i = 0; i < n; i ++) {
		scanf("%d", &x);
		cnt[x] ++;
	}
	f[n][0] = 1;
	for(int i = n; i; i --)
		for(int j = 0; j <= n; j ++)
			if(f[i][j]) {
				int v = j + cnt[i];
				int inv = (LL)f[i][j] * fact[v] % mod;
				for(int k = 0, t = 0; t <= v; k ++, t += i) {
					f[i - 1][v - t] = (f[i - 1][v - t] + (LL)inv * infact[k] % mod * infact[v - t] % mod) % mod;
					inv = (LL)inv * infact[i] % mod;
				}
			}
	printf("%d\n", f[0][0]);
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...