zoukankan      html  css  js  c++  java
  • BZOJ2616 : SPOJ PERIODNI

    长为$A$,宽为$B$的矩阵放$K$个车的方案数$=C(A,K) imes C(B,K) imes K!$。

    建立笛卡尔树,那么左右儿子独立,设$f[i][j]$表示$i$子树内放$j$个车的方案数。

    合并左右儿子之后,枚举在底部矩形放几个车进行转移即可。

    时间复杂度$O(n^3)$。

    #include<cstdio>
    const int N=505,M=1000005,P=1000000007;
    int n,m,i,a[N],mx,fac[M],inv[M],g[N],f[N][N];
    inline int cal(int a,int b,int k){
      if(a<k||b<k)return 0;
      return 1LL*fac[a]*inv[a-k]%P*inv[k]%P*fac[b]%P*inv[b-k]%P;
    }
    int dp(int l,int r,int h){
      if(l>r)return 0;
      int i,j,x=l;
      for(i=l;i<=r;i++)if(a[i]<a[x])x=i;
      int u=dp(l,x-1,a[x]),v=dp(x+1,r,a[x]);
      for(i=0;i<=r-l;i++)g[i]=0;
      for(i=0;i<=x-l;i++)if(f[u][i])for(j=0;j<=r-x;j++)g[i+j]=(1LL*f[u][i]*f[v][j]+g[i+j])%P;
      for(i=0;i<=r-l+1;i++)for(f[x][i]=j=0;j<=r-l&&j<=i;j++)f[x][i]=(1LL*g[j]*cal(r-l+1-j,a[x]-h,i-j)+f[x][i])%P;
      return x;
    }
    int main(){
      scanf("%d%d",&n,&m);
      for(mx=n,i=1;i<=n;i++)scanf("%d",&a[i]),mx=a[i]>mx?a[i]:mx;
      for(fac[0]=i=1;i<=mx;i++)fac[i]=1LL*fac[i-1]*i%P;
      for(inv[0]=inv[1]=1,i=2;i<=mx;i++)inv[i]=1LL*P/i*(P-inv[P%i])%P;
      for(i=2;i<=mx;i++)inv[i]=1LL*inv[i-1]*inv[i]%P;
      return printf("%d",f[dp(f[0][0]=1,n,0)][m]),0;
    }
    

      

  • 相关阅读:
    swagger生成接口文档
    二分查找通用模板
    go-json技巧
    【Go】获取用户真实的ip地址
    数据库储存时间类型
    密码加密:md5/sha1 +盐值
    参数里时间格式的转换
    不好定位的元素定位
    vim编辑器
    ps -ef | grep php kill -9
  • 原文地址:https://www.cnblogs.com/clrs97/p/6485317.html
Copyright © 2011-2022 走看看