loj6094 归乡迷途 / CF814E - dp、计数
Description
给出 \(n\) 个点,和每个点的度构造出一张无向图满足以下两条性质:
- 点 \(1\) 到点 \(i\) 仅有唯一一条最短路
- 点 \(1\) 到点 \(i\) 的最短路长度大于等于点 \(1\) 到点 \(i-1\) 的最短路长度
求能构成满足条件的无向图的个数?
Solution
咕咕咕。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int _ = 500 + 10;
int N, d[_];
ll f[_][_], g[_][_][_];
ll fac[_], facinv[_];
ll fastPow(ll a, ll b) {
ll ans = 1;
for (; b; b >>= 1) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
}
return ans;
}
void init() {
fac[0] = facinv[0] = 1;
for (int i = 1; i <= N; ++i) fac[i] = fac[i - 1] * i % mod;
facinv[N] = fastPow(fac[N], mod - 2);
for (int i = N - 1; i >= 1; --i) facinv[i] = facinv[i + 1] * (i + 1) % mod;
}
inline ll C(ll m, ll n) {
return fac[m] * facinv[n] % mod * facinv[m - n] % mod;
}
inline void Inc(ll &x, ll y) { x += y, x = x >= mod ? x - mod : x; }
int main() {
#ifndef ONLINE_JUDGE
freopen("return.in", "r", stdin);
freopen("return.out", "w", stdout);
#endif
scanf("%d", &N);
for (int i = 1; i <= N; ++i) scanf("%d", &d[i]);
init();
g[0][0][0] = 1;
for (int i = 0; i <= N; ++i) {
for (int j = 0; j <= N - i; ++j) {
if (!i && !j) continue;
if (!i) {
for (int k = 2; k <= j - 1; ++k)
Inc(g[0][i][j], g[0][i][j - k - 1] * C(j - 1, k) % mod * fac[k] %
mod * facinv[2] % mod);
} else {
if (i >= 2) Inc(g[0][i][j], (i - 1) * g[0][i - 2][j] % mod);
if (j >= 1) Inc(g[0][i][j], j * g[0][i][j - 1] % mod);
}
}
}
for (int i = 1; i < N; ++i) {
for (int p = 0; p < N - i; ++p) {
for (int k = 0; k <= p; ++k) {
int j = p - k;
if (!j && !k) continue;
if (j > 0) Inc(g[i][j][k], j * g[i - 1][j - 1][k] % mod);
if (k > 0) Inc(g[i][j][k], k * g[i - 1][j + 1][k - 1] % mod);
}
}
}
f[d[1] + 1][d[1]] = 1;
for (int i = d[1] + 2; i <= N; ++i) {
for (int j = 1; j <= i - d[1] - 1; ++j) {
int c[2] = {0};
for (int k = 1; k < i - j; ++k) {
++c[d[i - j - k + 1] - 2];
Inc(f[i][j], f[i - j][k] * g[j][c[0]][c[1]] % mod);
}
}
}
ll ans = 0;
int c[2] = {0};
for (int i = 1; i < N; ++i) {
++c[d[N - i + 1] - 2];
Inc(ans, f[N][i] * g[0][c[0]][c[1]] % mod);
}
cout << ans << endl;
return 0;
}
既然选择了远方,便只顾风雨兼程。