zoukankan      html  css  js  c++  java
  • bzoj 2734 [HNOI2012]集合选数 状压DP+预处理

    这道题很神啊……

    神爆了……

    思路大家应该看别的博客已经知道了,但大部分用的插头DP。我加了预处理,没用插头DP,一行一行来,速度还挺快。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #define N 100100
    #define M 50
    #define yu 1000000001
    #define inf 1<<29
    using namespace std;
    int n;
    long long ans=1;
    long long f[2][N/M]={0};
    int keneng[N/M],kenengnum;
    int sushu[N],sushunum;
    
    void make_sushu(int limit) // 这里不是筛素数,而是把不是2,3的倍数的筛出来 
    {                          // 如果筛素数,25不是素数,但是5的矩阵不能包含25 
        int i,j,k;
        int vis[N]={0};
        sushunum=0;
        for (i=1;i<=limit;i++)
            if (i%2!=0&&i%3!=0)
                sushu[++sushunum]=i;
    }
    
    bool shifou(int now)    // 预处理的判断,判断是否有两个1相连 
    {                         // 即是否取连续的两个数
        int i,j,k;
        i=now&1; now>>=1;
        while (now!=0)
        {
            j=now&1;
            if (i==j&&i&&j)
                return false;
            i=j;
            now>>=1;
        }
        return true;
    }
    
    void chuli(int limit)  //预处理,把可以选的状态存起来,省时间 
    {
        int i,j,k;
        int maxn=1;
        kenengnum=0;
        for (i=1;i<=limit;i++)
          maxn*=2;
        for (i=0;i<maxn;i++)
        {
            if (shifou(i))
            {
                keneng[kenengnum++]=i;
            }
        }
    }
    
    int pd_long(int x) // 由于矩阵每一行长度不同,所以预处理某些不能用 
    {                  // 这个判断每一行长度 
        int i=1,zanshi=0;
        while (i<=x)
        {
            zanshi++;
            i*=3;
        }
        return zanshi;
    }
    
    long long make_juzhen(int now)
    {
        int i,j,k,x=1,y,z;
        int limit,lnow,lnowbefore=inf;
        limit=pd_long(n/now);
        chuli(limit);
        f[0][0]=1;
        for (i=1;x*now<=n;i++,x*=2)
        {
            memset(f[i%2],0,sizeof(f[i%2]));
            lnow=pd_long(n/now/x);  // 当前行的长度 
            for (j=0;j<kenengnum;j++)
            {
                if (keneng[j]>>lnow>0) //如果有选超过当前行长度的,不选 
                {
                    f[i%2][j]=0;
                    continue;
                }
                for (k=0;k<kenengnum;k++) // 和上一行比较,是否有相连的1选了 
                {
                    if (keneng[k]>>lnowbefore>0) // 上一行状态不能超过上一行长度 
                        continue;
                    if (keneng[j]&keneng[k])
                        continue;
                    f[i%2][j]+=f[(i+1)%2][k];
                    f[i%2][j]%=yu;
                }
            }
            lnowbefore=lnow;  // 上一行长度 
        }
        return (f[(i+1)%2][0]+f[(i+1)%2][1])%yu; //最后一行一定只有一个,答案只有这两种情况加起来,最后一个选或不选 
    }
    
    int main()
    {
        int i,j,k,x,y,z;
        cin>>n;
        make_sushu(n);
        for (i=1;i<=sushunum;i++)
        {
               ans*=make_juzhen(sushu[i]);
               ans%=yu;
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    取得窗口大小和窗口位置兼容所有浏览器的js代码
    一个简单易用的导出Excel类
    如何快速启动chrome插件
    网页表单设计案例
    Ubuntu下的打包解包
    The source file is different from when the module was built. Would you like the debugger to use it anyway?
    FFisher分布
    kalman filter
    Group delay Matlab simulate
    24位位图格式解析
  • 原文地址:https://www.cnblogs.com/handsomeJian/p/3655608.html
Copyright © 2011-2022 走看看