zoukankan      html  css  js  c++  java
  • BZOJ3591: 最长上升子序列

    因为是一个排列,所以可以用$n$位二进制数来表示$O(nlog n)$求LIS时的单调栈。

    首先通过$O(n^22^n)$的预处理,求出每种LIS状态后面新加一个数之后的状态。

    设$f[i][j]$表示已选数字集合为$i$,LIS状态为$j$的方案数。

    转移时枚举不在$i$里的数$t$,如果$t$在给定的LIS中,那么它加入时需要检验它的前一个是否已经被加入。

    对于状态的存储,可以考虑三进制,0表示没选,1表示选了但是不在栈中,2表示在栈里。那么只要将两个二进制数看作三进制,然后相加即可。

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

    #include<cstdio>
    #define N 15
    int n,m,i,j,k,p[N],g[N][1<<N],pow[N],a[1<<N],f[14348907],ans;
    int main(){
      scanf("%d%d",&n,&m);
      for(i=0;i<n;i++)p[i]=-1;
      for(i=0;i<m;i++)scanf("%d",&j),p[j-1]=k-1,k=j;
      for(pow[0]=i=1;i<n;i++)pow[i]=pow[i-1]*3;
      for(i=0;i<1<<n;i++)for(j=0;j<n;j++)if(!(i>>j&1)){
        g[j][i]=i|(1<<j);
        for(k=j+1;k<n;k++)if(i>>k&1)break;
        if(k<n)g[j][i]^=1<<k;
      }else a[i]+=pow[j];
      for(i=0;i<n;i++)if(p[i]<0)f[pow[i]<<1]=1;
      for(i=1;i<1<<n;i++)for(k=0;k<n;k++)if(!(i>>k&1)){
        if(~p[k])if(!(i>>p[k]&1))continue;
        for(j=i;j;j=(j-1)&i)if(f[a[i]+a[j]])f[a[i|(1<<k)]+a[g[k][j]]]+=f[a[i]+a[j]];
      }
      for(i=1;i<1<<n;i++)if(__builtin_popcount(i)==m)ans+=f[a[(1<<n)-1]+a[i]];
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    C# richTextBox封装的一个打印的类
    RichtextBox打印
    RichTextBox选中文本时往自己的其他的位置实现拖拽
    C# 保存和读取TreeView展开的状态
    RichtextBox去除闪烁光标
    自己重启自己
    记录一次shell里局部变量的问题
    Redis配置总结
    Nginx原理和配置总结
    CentOS7+Nginx+多个Tomcat配置
  • 原文地址:https://www.cnblogs.com/clrs97/p/5201956.html
Copyright © 2011-2022 走看看