首页 > 其他 > 详细

【NOIP2017模拟6.25】小W的动漫

时间:2018-05-22 13:50:48      阅读:204      评论:0      收藏:0      [点我收藏+]

题目

小W最近迷上了日本动漫,每天都有无数部动漫的更新等着他去看,所以他必须将所有的动漫排个顺序,当然,虽然有无数部动漫,但除了1号动漫,每部动漫都有且仅有一部动漫是它的前传(父亲),也就是说,所有的动漫形成一个树形结构。而动漫的顺序必须满足以下两个限制:
1、一部动漫的所有后继(子孙)都必须排在它的后面;
2、对于同一部动漫的续集(孩子),小W喜爱度高的须排在前面。
光排序小W还不爽,他想知道一共有多少种排序方案,并且输出它mod 10007的答案。

分析

这个题目有两个限制:
1、先父亲后儿子;2、先大儿子后小儿子。
这个处理起来就很麻烦,
于是,我们可以转化一下模型,
对于限制2,因为大儿子一定比小儿子先遍历,那么我们可以将小儿子当做前一个比它大的儿子的儿子。
如样例:技术分享图片
现在,限制就只剩下“先父亲后儿子”,即求遍历一棵树,当父亲被走过才可以走儿子的方案数
显然,这是一棵二叉树。
\(f[x]\)表示,遍历以x为根的子树的方案数。
转移:
设两个儿子分别为i,j(只有一个儿子的话,f[x]就等于儿子的f值),以i为根的子树大小为s1,j的为s2;
\[f[x]=f[i]*f[j]*C^{min(s1,s2)}_{s1+s2}\](C组合求的是插板问题)
其实就是当前有s1个点,按顺序插入s2个点中。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const long long mo=10007;
const int N=1005;
using namespace std;
long long son[N][2],size[N],f[N],jc[N*3],ny[N*3],n,m,T;
long long mi(long long x,long long y)
{
    long long sum=1;
    while(y) 
    {
        if(y&1) sum=sum*x%mo;
        x=x*x%mo;
        y>>=1;
    }
    return sum;
}
long long C(long long mm,long long nn)
{
    if(nn>mm) swap(nn,mm);
    return jc[mm]*ny[nn]%mo*ny[mm-nn];
}
void dg(int x)
{
    size[x]=1;
    int j=son[x][0],k=son[x][1];
    if(j) dg(j);
    if(k) dg(k);
    int s1=size[j],s2=size[k];
    size[x]+=s1+s2;
    if(j && k) f[x]=f[j]%mo*f[k]%mo*C(s1+s2,min(s1,s2))%mo;
    else
    if(j) f[x]=f[j];
    else f[x]=1;
}
int main()
{
    jc[0]=ny[0]=1;
    for(int i=1;i<=3000;i++)
    {
        jc[i]=jc[i-1]*i%mo;
        ny[i]=mi(jc[i],mo-2);
    }
    scanf("%lld",&T);
    for(;T--;)
    {
        memset(son,0,sizeof(son));
        memset(size,0,sizeof(size));
        memset(f,0,sizeof(f));
        f[0]=1;
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
        {
            
            int last=i,x,k;
            scanf("%d",&k);
            for(int i=1;i<=k;i++)
            {
                scanf("%d",&x);
                if(!son[last][0]) son[last][0]=x;
                else son[last][1]=x;
                last=x;
            }
        }
        dg(1);
        printf("%lld\n",f[1]);
    }
}

【NOIP2017模拟6.25】小W的动漫

原文:https://www.cnblogs.com/chen1352/p/9071421.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!