zoukankan      html  css  js  c++  java
  • BZOJ 2734 洛谷 3226 [HNOI2012]集合选数【状压DP】【思维题】

    【题解】

      思维题,看了别人的博客才会写。

      写出这样的矩阵:

      1,3,9,...

      2,6,18,...

      4,12.36,...

      8,24,72,...

      我们要做的就是从矩阵中选出一些数字,但是不能选相邻的。

      我们可以发现,在100000的范围内,这个矩阵最多只有18行,11列。

      那么这个矩阵的取数字的方案数直接状压DP即可。f[i][j]表示第i行,状态为j的方案数,转移就是f[i][j]=sigma(f[i-1][k]) ,条件是(j&k==0且k&(k>>1)==0)

      但是这个矩阵不能覆盖值域之内的所有数字,怎么办呢?我们可以找到最小的没有被覆盖的数,用它放在(1,1)的位置构造一个类似的矩阵。

      可以证明每个数字恰好在矩阵中出现一次。所以最终答案就是各个矩阵的答案相乘。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define LL long long
     5 #define rg register
     6 #define N 50
     7 #define MOD(x) ((x)>=mod?(x)-mod:(x))
     8 using namespace std;
     9 const int mod=1000000001;
    10 int n,ans=1,a[N][N],mx[N],f[N][2048],exp[N];
    11 bool vis[100010];
    12 inline int read(){
    13     int k=0,f=1; char c=getchar();
    14     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    15     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    16     return k*f;
    17 }
    18 
    19 inline int calc(int x){
    20     memset(mx,0,sizeof(mx)); memset(f,0,sizeof(f));
    21     a[1][1]=x;
    22     for(rg int i=2;i<=18;i++)a[i][1]=(a[i-1][1]*2<=n)?a[i-1][1]<<1:n+1;
    23     for(rg int i=1;i<=18;i++)
    24         for(rg int j=2;j<=11;j++) a[i][j]=(a[i][j-1]*3<=n)?a[i][j-1]*3:n+1;
    25     for(rg int i=1;i<=18;i++)
    26         for(rg int j=1;j<=11;j++)if(a[i][j]<=n){
    27             mx[i]+=exp[j-1];
    28             vis[a[i][j]]=1;
    29         }
    30     f[0][0]=1;
    31     for(rg int i=1;i<=18;i++)
    32         for(rg int j=0;j<=mx[i];j++)if(!(j&(j>>1)))
    33             for(rg int k=0;k<=mx[i-1];k++)if(!(j&k)&&!(k&(k>>1)))
    34                 f[i][j]=MOD(f[i][j]+f[i-1][k]);
    35     return f[18][0];
    36 }
    37 int main(){
    38     exp[0]=1; for(rg int i=1;i<20;i++) exp[i]=exp[i-1]<<1;
    39     n=read();
    40     for(rg int i=1;i<=n;i++)if(!vis[i]) ans=(1ll*ans*calc(i))%mod;
    41     printf("%d",ans);
    42     return 0;
    43 }
  • 相关阅读:
    火车头采集器如何采集QQ群成员中的QQ号
    Unix目录结构的来历
    加速Windows 2003关机速度的设置方法
    win2003 序列号 windows2003 sp2可用序列号大全(准版与企业版)
    自己动手在win2003系统中添加虚拟网卡
    Windows Server 2003下DHCP服务器的安装与简单配置图文教程
    win2003远程桌面怎么切换到多用户?
    Win2003打开网页时总是提示添加网址到信任站点的设置方法
    我们正在招聘java工程师,想来美团工作吗?
    JUC回顾之-AQS同步器的实现原理
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9923497.html
Copyright © 2011-2022 走看看