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;
    }
  • 相关阅读:
    VisualVM 分析full GC问题记录
    HTTPS协议、TLS协议、证书认证过程解析
    java.lang基础数据类型boolean、char、byte、short、int、long、float、double (JDK1.8)
    java.lang.StringBuilder和java.lang.StringBuffer (JDK1.8)
    MVC中自带的异步((Ajax.BeginForm)无效
    百度富文本编辑器UEDITOR
    只有在配置文件或 Page 指令中将 enableSessionState 设置为 true 时,才能使用会话状态。还请确保在应用程序配置的 // 节中包括 System.Web.SessionSta
    【知识碎片】CSS 篇
    js 将json字符串转换为json对象的方法解析
    【知识碎片】Asp.Net 篇
  • 原文地址:https://www.cnblogs.com/handsomeJian/p/3655608.html
Copyright © 2011-2022 走看看