loj6094 归乡迷途 / CF814E - dp、计数

Description

给出 \(n\) 个点,和每个点的度构造出一张无向图满足以下两条性质:

  1. \(1\) 到点 \(i\) 仅有唯一一条最短路
  2. \(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;
}
posted @ 2020-06-15 16:11  newbielyx  阅读(141)  评论(0编辑  收藏  举报