Uva 11174 Stand in a Line 문제 풀이 보고서(증분 + 역원)

1521 단어 점차 미루다
문제풀이 보고서: 유여가 선생님의 책 제목.추리가 매우 정교하다는 것을 인정하지 않을 수 없다.역원, 나무를 두루 돌아다니는 것은 어려운 일이 아니다. 어려운 점은 이 추측된 공식에 있다.
코드는 다음과 같습니다.
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int mod = 1000000007;
typedef long long LL;

int powMod(LL a, int b)
{
    LL res = 1;
    while(b)
    {
        if(b&1)
            res = res*a%mod;
        b>>=1;
        a = a*a%mod;
    }
    return (int)res;
}

int inv(int n)
{
    return powMod(n, mod-2);
}

const int maxn = 40010;
int first[maxn],nxt[maxn],vv[maxn];
bool isSon[maxn];
int factorial[maxn];
LL ans;

void init()
{
    factorial[0] = 1;
    for(int i=1;i<maxn;i++)
        factorial[i] = (long long)factorial[i-1]*i%mod;
}

int dfsTree(int n,int p=0)
{
    int sonNum=1;
    for(int e=first[n];e;e=nxt[e])
        sonNum+=dfsTree(vv[e],n);

    if(sonNum>1) ans = ans*inv(sonNum)%mod;
    return sonNum;
}

void work()
{
    int n,m;
    scanf("%d%d",&n,&m);
    ans = factorial[n];

    int e = 2;
    memset(first, 0, sizeof(first));
    memset(isSon, 0, sizeof(isSon));
    while(m--)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        nxt[e] = first[v], vv[e] = u, first[v] = e++;
        isSon[u] = true;
    }

    for(int i=1;i<=n;i++) if(!isSon[i])
        dfsTree(i);

    printf("%d
", (int)ans); } int main() { init(); int T; scanf("%d", &T); while(T--) work(); }

좋은 웹페이지 즐겨찾기