码迷,mamicode.com
首页 > 其他好文 > 详细

[JZOJ5165] 小W的动漫

时间:2019-09-08 22:42:49      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:接下来   限制   它的   oid   size   for   def   read   using   

[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}\times 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\n",tr[1]);
    }
    return 0;
}
/*
  1
  5
  3 4 3 2
  0
  1 5
  0
  0
*/

[JZOJ5165] 小W的动漫

标签:接下来   限制   它的   oid   size   for   def   read   using   

原文地址:https://www.cnblogs.com/nlKOG/p/11488403.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!