JZOJ5418. 【NOIP2017提高A组集训10.24】 树形DP+组合数

来源:互联网 发布:brew mysql 编辑:程序博客网 时间:2024/06/05 15:49

题意:给出n个数,有一些特定要求,形如x,y表示x一定要在y的左边,求排列方案数。

一早上死想序列做法,想到了一下连边然后否决了。。然后想出了50分的容斥或者状压,然后觉得100分是不是再优化一下啥的,然后就再没脱出坑。。
事实证明部分分做法不一定是正解做法的暴力版本。。
首先有一个条件就是每一个人最多提出一个要求。
那么连边后的dag是一个森林,不相交的n棵树。
那么对于每一棵树,我们从下往上扫,记录当前走过的点数,设为sz,那么有:
g[x]=g[v]C(size[x],size[v])
表示以x为根的方案数,这个用乘法原理很好理解,每一颗子树是独立的。
然后答案也是一样的,相当于有一个超级根把所有树连在一起,所以就有:
ans=g[i]C(sz,size[i]),同理,也是独立的,直接乘就好。
看来思维不能太固定了= =。

#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=2e5+5;int head[N],next[N],go[N],size[N],d[N];int tot,fac[N],inv[N],n,m,mo,f[N],g[N];inline void add(int x,int y){    go[++tot]=y;    next[tot]=head[x];    head[x]=tot;}inline int find(int x){    if (f[x]==x) return x;    else return f[x]=find(f[x]);}inline int C(int n,int m){    return 1ll*fac[n]*inv[m]%mo*inv[n-m]%mo;}inline void dfs(int x){    g[x]=1;size[x]=0;    for (int i=head[x];i;i=next[i])    {        int v=go[i];        dfs(v);        size[x]+=size[v];        g[x]=1ll*g[x]*g[v]%mo*C(size[x],size[v])%mo;    }    size[x]++;}int main(){    freopen("photo.in","r",stdin);freopen("photo.out","w",stdout);    int cas;    scanf("%d",&cas);    while(cas--)    {        scanf("%d%d%d",&n,&m,&mo);        fac[0]=inv[0]=fac[1]=inv[1]=1;        fo(i,2,n)        fac[i]=1ll*fac[i-1]*i%mo,inv[i]=1ll*(mo-mo/i)*inv[mo%i]%mo;        fo(i,2,n)        inv[i]=1ll*inv[i]*inv[i-1]%mo;        fo(i,1,n)f[i]=i,head[i]=d[i]=0;        int flag=0;tot=0;        while (m--)        {            int x,y;            scanf("%d%d",&x,&y);            if (find(x)!=find(y))f[find(x)]=find(y);            else flag=1;            add(y,x);            d[x]++;        }        if (flag)        {            printf("0\n");            continue;        }        int ans=1,sz=0;        fo(i,1,n)        if (!d[i])        {            dfs(i);            sz+=size[i];            ans=1ll*ans*g[i]%mo*C(sz,size[i])%mo;        }        printf("%d\n",ans);    }}
阅读全文
0 0
原创粉丝点击