题目

有n个点,m个桥的有向图有多少?

思路

比较烦的一道题

代码

#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
using namespace std;
const int N = 105;
const int mod = 1e9 + 7; 
int n, B;
int C[N][N], P[N][N], P2[N * N], F[N];
int f[N][N], g[N][N][N];
int main() {
    freopen("bridge.in", "r", stdin);
    freopen("bridge.out", "w", stdout);
    for (int i = 0; i < N; i++) C[i][0] = 1;
    for (int i = 1; i < N; i++)
        for (int j = 1; j <= i; j++)
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
    for (int i = 1; i < N; i++) {
        P[i][0] = 1;
        for (int j = 1; j < N; j++) 
            P[i][j] = (ll)P[i][j  - 1] * i % mod;
    }
    P2[0] = 1;
    for (int i = 1; i < N * N; i++) 
        P2[i] = (ll)P2[i - 1] * 2 % mod;
    for (int i = 1; i < N; i++) {
        F[i] = P2[i * (i - 1) / 2];
        for (int j = 1; j < i; j++) {
            F[i] -= (ll)F[j] * C[i - 1][j - 1] % mod * P2[(i - j) * (i - j - 1) / 2] % mod;
            F[i] += mod;
            F[i] %= mod;
        }
    } 
    scanf("%d %d", &n, &B);
    for (int i = 1; i <= n; i++) {
        f[i][0] = F[i];
        for (int j = 1; j < i; j++) {
            for (int k = 0; k < i - j; k++) {
                for (int l = 1; l <= i - j; l++) {
                    f[i][0] -= (ll)f[j][0] * C[i - 1][j - 1] % mod * g[i - j][k][l] % mod * P[j][l] % mod;
                    f[i][0] += mod;
                    f[i][0] %= mod;
                }
            }
        }// cout << f[i][0] << "/" << F[i] << endl;
        //
        for (int j = 1; j < i; j++) {
            for (int k = 0; k < i - j; k++) {
                for (int l = 1; l <= i - j; l++) {
                    f[i][k + l] += (ll)f[j][0] * C[i - 1][j - 1] % mod * g[i - j][k][l] % mod * P[j][l] % mod;
                    f[i][k + l] %= mod;
                }
            }
        } 
        //
        for (int j = 0; j < i; j++) g[i][j][1] = (ll)f[i][j] * i % mod;
        for (int j = 1; j < i; j++) {
            for (int k = 0; k < j; k++) {
                for (int kk = 0; kk < i - j; kk++) {
                    for (int l = 1; l <= i - j; l++) {
                        g[i][k + kk][l + 1] += (ll)g[j][k][1] * C[i - 1][j - 1] % mod * g[i - j][kk][l] % mod;
                        g[i][k + kk][l + 1] %= mod;
                    }
                }
            }
        }
    }//cout << f[3][2] << endl;
    //for (int i = 0; i < 3; i++)
        //for (int j = 1; j <= 3; j++)
            //cout << "3" << " " << i << " " << j << " " << g[3][i][j] << endl;  
    ll ans = 0;
    B = min(B, n - 1);
    for (int i = 0; i <= B; i++) 
        (ans += f[n][i]) %= mod;
    cout << ans << endl;
} 

猜你喜欢

转载自blog.csdn.net/eric1561759334/article/details/80640812
今日推荐