UVA 11174

考虑每个人(t)的所有子女,在全排列中,t可以和他的任意子女交换位置构成新的排列,所以全排列n!/所有人的子女数连乘   即是答案 当然由于有MOD 要求逆。

 

#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
typedef long long ll;
const int N = 40005;
const ll MOD = 1e9+7;

int n, m;
ll v[N];
vector<int> g[N];

void init () {
    scanf("%d%d", &n, &m);

    memset(v, 0, sizeof(v));
    for (int i = 0; i <= n; i++)
        g[i].clear();

    int a, b;
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &a, &b);
        g[b].push_back(a);
    }
}

ll dfs(int x) {
    if (v[x])
        return v[x];

    for (int i = 0; i < g[x].size(); i++)
        v[x] += dfs(g[x][i]);
    return ++v[x];
}

void gcd (ll a, ll b, ll& x, ll& y, ll& d) {
    if (b == 0) {
        d = a;
        x = 1;
        y = 0;
    } else {
        gcd(b, a%b, y, x, d);
        y -= x*(a/b);
    }
}

int main () {
    int cas;
    scanf("%d", &cas);
    while (cas--) {
        init ();

        ll ans = 1, b = 1;
        for (ll i = 1; i <= n; i++)
            ans = (ans * i) % MOD;

        for (int i = 1; i <= n; i++)
            b = (b * dfs(i)) % MOD;

        ll p, k, d = 1;
        gcd(b, MOD, p, k, d);
        ans = ((ans * p) % MOD + MOD) % MOD;
        printf("%lld\n", ans);
    }
    return 0;
}

  

posted on 2017-07-25 20:48  Bingsen  阅读(180)  评论(0编辑  收藏  举报