「HNOI2008」明明的烦恼
prufer 序列题。
我们先考虑度数确定的点,记度数确定的点有 k 个,它们在 prufer 序列中一共出现 cnt 次。
首先我们要从 prufer 序列的 n−2 个位置中选 cnt 个来放这些点,然后我们考虑
先不确定其它 n−k 个点的位置,此时方案数为:{n - 2 \choose cnt}\frac{cnt!}{\prod_{d_i\ne-1} {(d_i - 1)!}}
那么剩下 n - k 个点怎么处理呢?我们考虑把他们直接塞到剩下 n - 2 - cnt 个空中去就好了 Q \omega Q ,方案数就是一个乘法原理:(n - k) ^ {n - 2 - cnt}
最后的答案就是 {n - 2 \choose cnt}\frac{cnt!}{\prod_{d_i\ne-1} {(d_i - 1)!}}(n - k) ^ {n - 2 - cnt}
稍微化简一下:
\begin{aligned}
ans
& = {n - 2 \choose cnt}\frac{cnt!}{\prod_{d_i\ne-1} {(d_i - 1)!}}(n - k) ^ {n - 2 - cnt} \\
& = \frac{(n - 2)!}{cnt! \times (n - 2 - cnt)!} \times \frac{cnt!}{\prod_{d_i\ne-1} {(d_i - 1)!}}(n - k) ^ {n - 2 - cnt} \\
& = \frac{(n - 2)!}{(n - 2 - cnt)! \times \prod_{d_i\ne-1} {(d_i - 1)!}}(n - k) ^ {n - 2 - cnt}
\end{aligned}
然后写个高精直接求就是了
参考代码:
#include <cstdio>
#include <vector>
using namespace std;
const int _ = 1e3 + 5;
struct BigInteger {
vector < int > s;
BigInteger() { s.clear(); }
BigInteger clean() { while (s.size() && !s.back()) s.pop_back(); return *this; }
BigInteger operator = (int x) {
s.clear();
while (x) s.push_back(x % 10), x /= 10;
return this -> clean();
}
BigInteger operator * (const int& x) {
int g = 0;
for (int i = 0; i < s.size(); ++i) s[i] *= x;
for (int i = 0; i < s.size(); ++i)
s[i] += g, g = s[i] / 10, s[i] %= 10;
while (g) s.push_back(g % 10), g /= 10;
return this -> clean();
}
BigInteger operator / (const int& x) {
int g = 0;
for (int i = s.size() - 1; i >= 0; --i) {
g = g * 10 + s[i];
if (g >= x) s[i] = g / x, g %= x; else s[i] = 0;
}
return this -> clean();
}
void output() { for (int i = s.size() - 1; i >= 0; --i) printf("%d", s[i]); puts(""); }
} ans;
int n, k, s, d[_];
int main() {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin), freopen("cpp.out", "w", stdout);
#endif
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", d + i);
if (n == 1) { puts(d[1] == -1 || d[1] == 0 ? "1" : "0"); return 0; }
for (int i = 1; i <= n; ++i) if (d[i] != -1) ++k, s += d[i] - 1;
if (s > n - 2) { puts("0"); return 0; }
ans = 1;
for (int i = 1; i <= n - 2; ++i) ans = ans * i;
for (int i = 1; i <= n - 2 - s; ++i) ans = ans * (n - k);
for (int i = 1; i <= n - 2 - s; ++i) ans = ans / i;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= d[i] - 1; ++j) ans = ans / j;
ans.output();
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步