• bzoj 2159 Crash 的文明世界 && hdu 4625 JZPTREE ——第二类斯特林数+树形DP


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2159

    学习材料:https://blog.csdn.net/litble/article/details/80882581

         https://www.cnblogs.com/Wuweizheng/p/8638858.html

         http://www.cnblogs.com/zhouzhendong/p/Stirling-Number.html

         https://blog.csdn.net/qq_35649707/article/details/79929407

         https://www.cnblogs.com/gzy-cjoier/p/8426987.html

    (O(nlogn)求第一类斯特林数一行的方法:https://www.mina.moe/archives/11349

    第二类斯特林数的公式: ( x^{n}=sumlimits_{k=0}^{n}C_{x}^{k}*k!*S(n,k) )

    所以一个点 t 的答案为  ( sumlimits_{j=1}^{N} sumlimits_{l=0}^{k}S(k,l)*l!*C_{dis(t,j)}^{l} )

                ( = sumlimits_{l=0}^{k}S(k,l)*l! sumlimits_{j=1}^{N}C_{dis(t,j)}^{l} )

    然后开始把那个 C 拆开什么的。最后去看题解了。

    原来那个 C 已经可以树形DP算了。设 ( f[ i ][ j ] = sumlimits_{k=1}^{N}C_{dis(i,k)}^{j} ) ,由 ( C_{i}^{j}=C_{i-1}^{j}+C_{i-1}^{j-1} ) 可以得到递推式(换根时):

      ( f[i][j]-=f[v][j-1]+f[v][j] )  ( f[v][j]=f[i][j-1]+f[i][j] )  (其中 i 是现在的根, v 是下一次的根)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=5e4+5,M=155,mod=10007;
    int n,m,hd[N],xnt,to[N<<1],nxt[N<<1];
    int f[N][M],g[N][M],s[M][M],jc[M];
    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;
    }
    void upd(int &x){x>=mod?x-=mod:0;}
    void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
    void init()
    {
      jc[0]=1;for(int i=1;i<=m;i++)jc[i]=jc[i-1]*i%mod;
      s[0][0]=1;
      for(int i=1;i<=m;i++)
        for(int j=1;j<=i;j++)
          s[i][j]=(s[i-1][j]*j+s[i-1][j-1])%mod;
    }
    void cz(int *a,int *b,int fx)
    {
      a[0]=(a[0]+mod+b[0]*fx)%mod;
      for(int j=1;j<=m;j++)
        a[j]=(a[j]+(b[j-1]+b[j])*fx)%mod+mod,upd(a[j]);
    }
    void dfs(int cr,int fa)
    {
      f[cr][0]=1;
      for(int i=hd[cr],v;i;i=nxt[i])
        if((v=to[i])!=fa)
          {
        dfs(v,cr);
        cz(f[cr],f[v],1);
          }
      memcpy(g[cr],f[cr],sizeof f[cr]);
    }
    void dfsx(int cr,int fa)
    {
      for(int i=hd[cr],v;i;i=nxt[i])
        if((v=to[i])!=fa)
          {
        cz(g[cr],f[v],-1);
        cz(g[v],g[cr],1);
        dfsx(v,cr);
        cz(g[cr],f[v],1);
          }
    }
    int main()
    {
      int L,now,A,B,Q,tmp,u,v;
      scanf("%d%d%d",&n,&m,&L); init();
      scanf("%d%d%d%d",&now,&A,&B,&Q);
      for(int i=1;i<n;i++)
        {
          now=(now*A+B)%Q;
          tmp=(i<L)?i:L;
          u=i-now%tmp; v=i+1;
          add(u,v); add(v,u);
        }
      dfs(1,0); dfsx(1,0);
      for(int i=1;i<=n;i++)
        {
          int ans=0;
          for(int j=0;j<=m;j++)
        ans=(ans+s[m][j]*jc[j]%mod*g[i][j])%mod;
          printf("%d
    ",ans);
        }
      return 0;
    }
    View Code

    UPD(2018.12.16):今天讲到 hdu 4625 ,竟然完全不记得做过。于是又打了一遍。hdu 交上去总是 CE ,重打了一遍 init( ) 里的括号就好了。难道是什么中文括号之类的?

    不过今天讲的是另一种想法,维护 x 的 n 次下降幂之类的。不管了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=5e4+5,M=505,mod=10007;
    int T,n,m,hd[N],xnt,to[N<<1],nxt[N<<1];
    int S[M][M],jc[M],f[N][M],ans[N];
    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;
    }
    void upd(int &x){while(x>=mod)x-=mod;while(x<0)x+=mod;}
    void init()
    {
      int lm=500;
      S[0][0]=1;
      for(int i=1;i<=lm;i++)
        for(int j=1;j<=i;j++)
          S[i][j]=(S[i-1][j-1]+(ll)S[i-1][j]*j)%mod;
      jc[0]=1;for(int i=1;i<=lm;i++)jc[i]=(ll)jc[i-1]*i%mod;
    }
    void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
    void add(int *a,int *b,int k)
    {
      a[0]+=b[0]*k;
      for(int j=1;j<=m;j++)
        a[j]+=(b[j-1]+b[j])*k,upd(a[j]);
    }
    void dfs(int cr,int fa)
    {
      f[cr][0]=1;
      for(int i=hd[cr],v;i;i=nxt[i])
        if((v=to[i])!=fa)
          {
        dfs(v,cr);add(f[cr],f[v],1);
          }
    }
    void dfsx(int cr,int fa)
    {
      ans[cr]=0;
      for(int i=0;i<=m;i++)
        ans[cr]=(ans[cr]+(ll)jc[i]*S[m][i]%mod*f[cr][i])%mod;
      for(int i=hd[cr],v;i;i=nxt[i])
        if((v=to[i])!=fa)
          {
        add(f[cr],f[v],-1);
        add(f[v],f[cr],1);
        dfsx(v,cr);
        add(f[v],f[cr],-1);
        add(f[cr],f[v],1);
          }
    }
    int main()
    {
      T=rdn();init();
      while(T--)
        {
          n=rdn();m=rdn();
          xnt=0;memset(hd,0,sizeof hd);
          for(int i=1,u,v;i<n;i++)
        u=rdn(),v=rdn(),add(u,v),add(v,u);
          memset(f,0,sizeof f);
          dfs(1,0);dfsx(1,0);
          for(int i=1;i<=n;i++)printf("%d
    ",ans[i]);
        }
      return 0;
    }
    View Code
  • 相关阅读:
    使用NSTask调用shell
    《UML和模式应用》读书笔记(一)
    iOS网络编程
    多线程
    Quartz2D
    沙盒中的数据存取
    UIButton设置为圆形按钮并增加边框
    Mac开发快速入门
    JavaWeb学习总结(三)response与request
    JavaWeb学习总结(二) Servlet
  • 原文地址:https://www.cnblogs.com/Narh/p/10069335.html
Copyright © 2020-2023  润新知