zoukankan      html  css  js  c++  java
  • bzoj2734:[HNOI2012]集合选数(状压DP)

      菜菜的喵喵题~

      化序列为矩阵!化腐朽为神奇!左上角为1,往右每次*3,往下每次*2,这样子就把问题转化成了在矩阵里选不相邻的数有几种可能。

      举个矩阵的例子

      1 3 9 27
      2 6 18 54
      4 12 36 108

      这样最多11列,最多17行,那么方案数就可以用状压了。 

      但是我们会发现,矩阵里没有5,所以我们要把5作为左上角再算一次答案,最后把所有矩阵的答案用乘法原理乘起来就好

    #include<iostream> 
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm> 
    #define MOD(x) ((x)>=mod?(x)-mod:(x))
    using namespace std;
    const int maxn=500010,mod=1e9+1;
    int n,ans,cnth;
    int f[20][1<<11],cntl[20];
    bool v[maxn];
    inline void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    inline int find(int x)
    {
        cnth=0;memset(cntl,0,sizeof(cntl));
        for(int i=1,fir=x;fir<=n;i++,fir*=2,cnth++)
        for(int j=1,sec=fir;sec<=n;j++,sec*=3,cntl[i]++)v[sec]=1;
        f[0][0]=1;
        for(int i=1;i<=cnth;i++)for(int j=0;j<=(1<<cntl[1])-1;j++)f[i][j]=0;
        for(int i=1;i<=cnth;i++)
        for(int j=0;j<(1<<cntl[i]);j++)
        if(!(j&(j>>1)))
        for(int k=0;k<(1<<cntl[i-1]);k++)
        if(!(k&(k>>1)))if(!(j&k))f[i][j]=MOD(f[i][j]+f[i-1][k]);
        int sum=0;
        for(int i=0;i<=(1<<cntl[cnth])-1;i++)sum=MOD(sum+f[cnth][i]);
        return sum;
    }
    int main()
    {
        read(n);ans=1;
        for(int i=1;i<=n;i++)
        if(!v[i])ans=1ll*ans*find(i)%mod;
        printf("%d
    ",ans);
    }
    View Code
  • 相关阅读:
    开发DBA(APPLICATION DBA)的重要性
    SQL有外连接的时候注意过滤条件位置
    程序与bug
    Dalvik虚拟机进程和线程的创建过程分析
    Dalvik虚拟机简要介绍和学习计划
    Dalvik虚拟机的运行过程分析
    JRE和JDK的概念
    myeclipse6.0.1(内置了eclipse)安装及其配置
    JDK 环境变量如何设置
    jdk1.5和tomcat5.5免安装的环境配置
  • 原文地址:https://www.cnblogs.com/Sakits/p/7693341.html
Copyright © 2011-2022 走看看