• 洛谷P4099 [HEOI2013]SAO(树形dp)


    传送门

    HEOI的题好珂怕啊(各种意义上)

    然后考虑树形dp,以大于为例

    设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小有关,与实际数值无关)

    我们考虑如果从当前子树中弄出$k$个节点,其他子树中弄出$j-1$个节点,那么当前节点的大小排名就是$k+j$

    然后考虑一下,如果我们不看这个子树,根节点排在第$j$个,方案数是$f[i][j]$,如果只看此子树,此子树的根就是根节点的儿子,它在此子树中的排名可能是$1,2,...k$,那么我们就需要记录一下前缀和

    然后考虑合并排列

    对于小于根节点的,选出$j-1$个非此子树,对于大于根节点的,选出$sum[x]-1$个非此子树里弄出来的,那么就是一个组合问题了

    ps:因为dp的时候会有4个1e9相乘所以要模四次

    然后上我这个卡常卡到丧心病狂的代码

     1 // luogu-judger-enable-o2
     2 //minamoto
     3 #include<iostream>
     4 #include<cstdio>
     5 #include<cstring>
     6 #define ll long long
     7 using namespace std;
     8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     9 char buf[1<<21],*p1=buf,*p2=buf;
    10 inline int read(){
    11     #define num ch-'0'
    12     char ch;bool flag=0;int res;
    13     while(!isdigit(ch=getc()))
    14     (ch=='-')&&(flag=true);
    15     for(res=num;isdigit(ch=getc());res=res*10+num);
    16     (flag)&&(res=-res);
    17     #undef num
    18     return res;
    19 }
    20 inline int getop(){
    21     char ch;while((ch=getc())!='<'&&ch!='>');return ch=='<'?1:-1;
    22 }
    23 void print(int x){
    24     if(x>=10) print(x / 10);
    25     putchar('0'+x%10);
    26 }
    27 const int N=1005,mod=1e9+7;
    28 int n,tot;ll tmp[N];
    29 int f[N][N],g[N][N],c[N][N];
    30 int head[N],ver[N<<1],Next[N<<1],sum[N],edge[N<<1];
    31 inline void init(){
    32     c[0][0]=1;
    33     for(int i=1;i<=1000;++i){
    34         c[i][0]=1;
    35         for(int j=1;j<=i;++j)
    36         c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
    37     }
    38 }
    39 inline void clear(){
    40     memset(head,0,sizeof(head));
    41     tot=0;
    42 }
    43 inline void add(int u,int v,int e){
    44     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
    45 }
    46 void dfs(int u,int fa){
    47     memset(g[u],0,sizeof(g[u])),memset(f[u],0,sizeof(f[u]));
    48     g[u][1]=f[u][1]=sum[u]=1;
    49     for(int i=head[u];i;i=Next[i]){
    50         int v=ver[i],e=edge[i];
    51         if(v==fa) continue;
    52         dfs(v,u);
    53         memset(tmp,0,sizeof(tmp));
    54         for(int j=1;j<=sum[u];++j)
    55         for(int k=0;k<=sum[v];++k){
    56             if(~e)
    57             tmp[j+k]+=1ll*f[u][j]*g[v][k]%mod
    58             *c[j+k-1][j-1]%mod*c[sum[u]+sum[v]-j-k][sum[u]-j]%mod;
    59             else tmp[j+k]+=1ll*f[u][j]*(g[v][sum[v]]-g[v][k]+mod)%mod
    60             *c[j+k-1][j-1]%mod*c[sum[u]+sum[v]-j-k][sum[u]-j]%mod;
    61         }
    62         sum[u]+=sum[v];
    63         for(int j=1;j<=sum[u];++j)
    64         f[u][j]=tmp[j]%mod,g[u][j]=(g[u][j-1]+f[u][j])%mod;
    65     }
    66 }
    67 int main(){
    68 //    freopen("testdata.in","r",stdin);
    69     int T=read();init();
    70     while(T--){
    71         clear();n=read();
    72         for(int i=1,u,v,e;i<n;++i){
    73             u=read(),e=getop(),v=read();
    74             add(u,v,e),add(v,u,-e);
    75         }
    76         dfs(1,-1);
    77         print(g[1][sum[1]]),putchar(10);
    78     }
    79     return 0;
    80 }
  • 相关阅读:
    django之表设计、路由层等
    django之三剑客、静态文件配置、请求响应对象、数据库操作
    djang小项目过程中的小问题 02(跳转界面)
    生鲜超市项目错误及解决办法(crispy_forms、外键指向自己、class嵌套访问父类、meta类及各种字段参数)
    生鲜超市项目错误及解决办法(安装mysqlclient)
    djang小项目过程中的小问题 01(django中的configrarion配置、django自带命名规范)
    react-Hook
    react中登录注册 使用验证码验证
    react状态管理器之mobx
    react中的虚拟DOM,jsx,diff算法。让代码更高效
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9648167.html
Copyright © 2020-2023  润新知