T392582 我有抑郁症【题解】

题目描述

要求有多少个序列满足:

  • \(v=1\sim n\)
  • \(v\) 号点开始,走到 \(p_v\),…,最后走回 \(v\)
  • 记录每个点被走到的次数(起点算,终点不算,反正只算一次)
  • \(i\) 号点走到的次数恰好是 \(i\)

答案对 \(998,244,353\) 取模

Solution

首先,一个点有一个出边,这个图为什么一定可以走回来?

因为这是个排列啊!不能有相同的入边,每个点只有一个出边,这是什么!这是环啊!

所以整个图就是若干个环,我们要在环上计数。

设我们当前的 \(a_i\) 统称为 \(k\)\(a_i=k\) 的点数量是 \(c_k\),则这个图有答案当且仅当 \(k | c_k\),为什么?

因为一个环上 \(a_i=k\),那么这个环只有 \(k\) 个点,\(a_i=k\) 的图有可能会有很多个由 \(k\) 个点组成的环,所以必须要 \(k\) 能被 \(c_k\) 整除

首先考虑这个图上有 \(\cfrac{c_k}{k}\) 个环,为了好描述,我们令 \(\cfrac{c_k}{k}=S\),那么我们先从大的角度入手,即分给每个环多少个元素

那肯定是从 \(c_k\) 个点选 \(k\) 个了,然后再从剩下 \(c_k-k\) 个点选 \(k\) 个,以此类推,即贡献为

\[\cfrac{\binom{c_k}{k}\binom{c_k-k}{k} …\binom{k}{k}}{S!} \]

然后在考虑每个环里的贡献,即有多少种不同的环可以符合条件

我一开始想 \(1\) 号点不能在第一个,好难搞啊

但是后面大佬们告诉我,不要考虑细节,直接构造一个环就完事了,想想也确实是这样

因为你这个序列肯定是个环,因为具体在 \(1\) 号点填的是这条出边的终点,所以相当于求本质不同的环的个数!!!

所以就是圆排列,也就是 \((k-1)!\) 了,然后有 \(S\) 组,相乘就好了

也就是贡献是:

\[\cfrac{\binom{c_k}{k}\binom{c_k-k}{k} …\binom{k}{k}}{S!} \times (k-1)!^{S} \]

做完了,以下是代码

#include <bits/stdc++.h>

using namespace std;

int T;

const int MAXN = 5e5 + 7;

typedef long long ll;

const ll Mod = 998244353;

ll Fac[MAXN], Inv[MAXN];

int n; 

ll qpow(ll a, ll b) {
	ll ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % Mod;
		a = a * a % Mod, b >>= 1;
	}
	return ans;
}

int A[MAXN];

ll ans = 1;

ll C(int n, int m) { return Fac[n] * Inv[m] % Mod * Inv[n - m] % Mod; }

int main () {
	ios :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
	
	cin >> T;
	
	Fac[0] = 1;
	for (int i = 1; i <= 500000; i ++) Fac[i] = Fac[i - 1] * i % Mod;
	Inv[500000] = qpow(Fac[500000], Mod - 2);
	for (int i = 500000 - 1; i >= 0; i --) Inv[i] = Inv[i + 1] * (i + 1) % Mod;
	
	while (T --) {
		cin >> n; memset(A, 0, sizeof(A)); ans = 1;
		for (int i = 1, x; i <= n; i ++) cin >> x, A[x] ++;
		for (int i = 2; i <= n; i ++) {
			if (A[i] % i && A[i]) ans = 0;
			else if (A[i]){
				for (int j = 0; A[i] - j * i > 0; j ++) ans = ans * C(A[i] - i * j, i) % Mod;
				ans = ans * Inv[A[i] / i] % Mod * qpow(Fac[i - 1], (A[i] / i)) % Mod;	
			}
		}
		cout << ans << '\n';
	} 
	return 0;
}

完结撒花✿✿ヽ(°▽°)ノ✿

posted @ 2023-11-04 15:12  Phrvth  阅读(8)  评论(0编辑  收藏  举报