• 洛谷 4099 [HEOI2013]SAO——树形DP


    题目:https://www.luogu.org/problemnew/show/P4099

    结果还是看了题解才会……

    关键是状态,f[ i ][ j ] 表示 i 子树、 i 号点是第 j 个出现的方案数。

    合并的时候,很重要的是去枚举孩子 v 有 k 个点放在了第 i 个点前面。这样 v 可以在的位置就根据该边是 > 还是 < 而是一个前/后缀。这样就是 n2 的了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    int Mn(int a,int b){return a<b?a:b;}
    const int N=1005,mod=1e9+7;
    int upt(int x){while(x>=mod)x-=mod;while(x<0)x+=mod;return x;}
    
    int n,siz[N],c[N][N],f[N][N],pr[N][N],sc[N][N];
    int hd[N],xnt,to[N<<1],nxt[N<<1];bool lx[N<<1];//1:<
    char ch;
    void add(int x,int y,bool fx)
    { to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;lx[xnt]=fx;}
    void dfs(int cr,int fa)
    {
      siz[cr]=1; f[cr][1]=1;//
      for(int i=hd[cr],v;i;i=nxt[i])
        if((v=to[i])!=fa)
          {
        dfs(v,cr); siz[cr]+=siz[v];
        for(int j=siz[cr];j;j--)
          {
            int lj=0;
            for(int k=0,l2=Mn(j-1,siz[v]);k<=l2;k++)
              {
            int tp=0;
            if(lx[i]) tp=(ll)f[cr][j-k]*sc[v][k+1]%mod;
            else tp=(ll)f[cr][j-k]*pr[v][k]%mod;
            tp=(ll)tp*c[j-1][k]%mod*c[siz[cr]-j][siz[v]-k]%mod;
            lj=upt(lj+tp);
              }
            f[cr][j]=lj;
          }
          }
      pr[cr][0]=sc[cr][siz[cr]+1]=0;///
      for(int j=1;j<=siz[cr];j++)
        {
          pr[cr][j]=upt(pr[cr][j-1]+f[cr][j]);
        }
      for(int j=siz[cr];j;j--)
        {
          sc[cr][j]=upt(sc[cr][j+1]+f[cr][j]);
        }
      pr[cr][0]=sc[cr][siz[cr]+1]=0;
    }
    int main()
    {
      int T=rdn(),lm=1000;
      for(int i=0;i<=lm;i++)c[i][0]=1;
      for(int i=1;i<=lm;i++)
        for(int j=1;j<=i;j++)
          c[i][j]=upt(c[i-1][j]+c[i-1][j-1]);
      while(T--)
        {
          n=rdn(); memset(hd,0,sizeof hd); xnt=0;
          for(int i=1,u,v;i<n;i++)
        {
          u=rdn()+1;cin>>ch;v=rdn()+1;
          add(u,v,ch=='<'); add(v,u,ch=='>');
        }
          dfs(1,0);
          printf("%d
    ",sc[1][1]);
        }
      return 0;
    }
  • 相关阅读:
    SpringCloud(四)GateWay网关
    C++中的间接宏函数
    一个C++引用库的头文件预编译陷阱
    谈谈C++中的数据对齐
    在C++中实现aligned_malloc
    WPF中的DesignerProperties
    在.NET 6中使用DateOnly和TimeOnly
    在 Ubuntu 上安装 .NET SDK 或 .NET 运行时
    Microsoft Build 2021第二天
    Microsoft Build 2021大会开始后,Develop Blog一系列更新
  • 原文地址:https://www.cnblogs.com/Narh/p/10883794.html
Copyright © 2020-2023  润新知