zoukankan      html  css  js  c++  java
  • [JZOJ5165] 小W的动漫

    [JZOJ5165] 小W的动漫

    (sort.cpp 1s 256M)
    小WW最近迷上了日本动漫,每天都有无数部动漫的更新等着他去看,所以他必须将所有的动漫排个顺序,当然,虽然有无数部动漫,但除了1号动漫,每部动漫都有且仅有一部动漫是它的前传(父亲),也就是说,所有的动漫形成一个树形结构。而动漫的顺序必须满足以下两个限制:
    ①一部动漫的所有后继(子孙)都必须排在它的后面。
    ②对于同一部动漫的续集(孩子),小W喜爱度高的须排在前面。
    光排序小WW还不爽,他想知道一共有多少种排序方案,并且输出它mod10007的答案。
    Input
    第一行表示T表示数据组数。
    接下来每组数据第一行n表示有多少部动漫等待排序,
    接下来n行每行第一个数tot表示这部动漫有多少部续集,
    接下来tot个数按照小WW喜爱从大到小给出它的续集的编号。
    n≤1000。
    Output
    每组数据一行数ans,表示答案mod10007的结果。
    Sample Input
    1
    5
    3 4 3 2
    0
    1 5
    0
    0
    Sample Output
    2

    Solution

    对于以X为根的子树, 其能组成的所有排序中, X及X的儿子节点的相对位置是唯一的, 而在这些点之下的点就可以变换排列.

    设f(x)表示以x为根的子树能组成的合法序列个数;

    在以fa(x)为根的子树里, x的子孙节点只能排布在x之后, 假设x后已经排列有t个节点, 那么x的子孙节点就有(C_{sz(x)-1+t}^{sz(x)-1} imes f(x))种排列方式, 这也就是对f(fa(x))造成的贡献

    最后答案就是f(1)

    Code

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    int read(){
        int x=0,f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    const int N=1e3+28,p=10007;
    int n,sz[N],tr[N],tot[N],son[N][N];
    int mul[N],di[N];
    int Pow(int x,int y=p-2){
        int re=1;
        while(y){
    	if(y&1)re=re*x%p;
    	y>>=1;
    	x=x*x%p;
        }
        return re;
    }
    void Pre(int n=1000){
        mul[1]=di[1]=1;
        for(int i=2;i<=n;i++){
    	mul[i]=mul[i-1]*i%p;
    	di[i]=Pow(mul[i]);
        }
    }
    int C(int n,int m){
        if(m==0||n==m)return 1;
        int re=mul[n]*di[m]%p;
        re=re*di[n-m]%p;
        return re;
    }
    void dfs(int x=1){
        tr[x]=sz[x]=1;
        int fk=0;
        for(int i=tot[x];i>=1;i--){
    	dfs(son[x][i]);
    	sz[x]+=sz[son[x][i]];
    	tr[x]=tr[x]*C(fk+sz[son[x][i]]-1,fk)%p;
    	tr[x]=tr[x]*tr[son[x][i]]%p;
    	fk+=sz[son[x][i]];
        }
    }
    signed main(){
        //freopen("sort.in","r",stdin);
        //freopen("sort.out","w",stdout);
        Pre();
        int t=read();
        while(t--){
    	memset(tr,0,sizeof(tr));
    	n=read();
    	for(int i=1;i<=n;i++){
    	    tot[i]=read();
    	    for(int j=1;j<=tot[i];j++){
    		son[i][j]=read();
    	    }
    	}
    	dfs();
    	printf("%lld
    ",tr[1]);
        }
        return 0;
    }
    /*
      1
      5
      3 4 3 2
      0
      1 5
      0
      0
    */
    
    
  • 相关阅读:
    CodeForces Gym 100500A A. Poetry Challenge DFS
    CDOJ 486 Good Morning 傻逼题
    CDOJ 483 Data Structure Problem DFS
    CDOJ 482 Charitable Exchange bfs
    CDOJ 481 Apparent Magnitude 水题
    Codeforces Gym 100637G G. #TheDress 暴力
    Gym 100637F F. The Pool for Lucky Ones 暴力
    Codeforces Gym 100637B B. Lunch 找规律
    Codeforces Gym 100637A A. Nano alarm-clocks 前缀和
    TC SRM 663 div2 B AABB 逆推
  • 原文地址:https://www.cnblogs.com/nlKOG/p/11488403.html
Copyright © 2011-2022 走看看