题意:求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中。(结果对1e9+1取模)

分析:

  首先,什么样的数才会产生排斥呢?(选了这个不能选那个)    显然是之比是2或3的啦

  其次,很容易想明白的一点就是每个形如1,2,4,8,3,6,9.....这种以一个小的数通过*2*3往外延伸的数列,他们两两之间是互不干扰的

  比如,对于从1往外扩展的数列来说可以是1,2,4,8,3,9,27,6,12,24......

  他与从5往外扩展的一定是没有交集的,5,10,20,15,30,60……

  那么这里自然就很容易想到乘法原理,

  也就是说我们解决了每一个这种数列的结果只后只需要乘起来就是最终结果

  那么对于每个来说如何解决呢?

  首先如果只有之比是2的不能出现在子集中,

  第一感觉肯定是“这选相邻的不就完了”

  当然,下一秒就会回过神来,显然并不是一眼就能秒出来的(gjk等dalao除外)

  

  这两个题大部分人都过……     现在大家应该都会迫不及待的打断我“这玩意不就是B题互不侵犯的弱化版吗(甚至弱化到线性)”“这玩意我闭着眼都会打”,

  嗯,其实就是用二进制枚举一下这n个2^i里每个位置是否放数,显然如果k&(k>>1)!=0或者k&(k<<1)!=0的话就是不合法的,反之就是合法的

  那么现在加一个之比为3的限制又该怎么做呢?

  考虑,在没加这个限制之前每个以a为首项的公比为2的数列是互不影响的

  而加了这个限制以后这个等比数列里的每一项又与他*3,他*9……扯上了联系

  原来是一个一个数(点),加了第一个限制之后变成了一个数列(线)

  现在是一个数列(线),再加一个限制,那么变成?

  对,变成一个矩阵(面)

  所以这也填了开始的坑,为什么要将一个较小数,他*2*3放在一起考虑

  而且现在我们知道了,其实开始讲的数列他不是数列而是矩阵,大概长这样

  1  2  4  8  16

  3  6  12  24  48

  9  18  36  72  144

  ……

  而这个又该怎么才能排除掉不合法的呢?

  “这不还是B题的弱化版吗”“行了,我会了,再见了您嘞”

  没错,这里只需要用状压dp随便搞搞就行,具体的判断条件我相信大家用脚都能打出来,没错就是j&k!=0就不合法,反之合法

  最后再梳理一下

  首先我们要枚举“最小的数”,这里我用的是判断这个数是否不被2或3整除,

  这里类似线性筛,显然如果这个数能被2或3整除,他一定会有一个叫x/2或x/3的来充当“最小的数”

  枚举出来最小的数之后,第一列就是x,x*3,x*9,……

  然后就是算他每行的列数(x*(3^i)*(2^j)<=n)

  最后状压dp随便搞搞就行了

  其实这题到这已经基本结束了,但是不知道是不是我菜的原因,又双叒叕t了半天

  这边简单介绍几个优化(代码细节)

  1.把你单行的判断用一个数组存下状态

  比如原来要写for (0 -> 1<<k ) if(k&……)dp[k]……

  而现在我们只需要预处理之后 for(0->q.size()) dp[k]……

  2.取模->减法

  

  

  显然减法比取模快不少

  3.先用变量代替数组,最后赋值

  显然又快不少

  4.边干活边赋初值(不用memset,而是在用之前赋初值)

   这差的不是一点半点,千万不要一时偷懒调一晚!

  

  最后的最后,再把我关于处理某些细节的代码说一下

  1.选出“最小的数”

  

  这里之前说过了

  2.计算该行有多少列

  

  这里j是“最小的数”,这里其实应该是以2为底n/j的对数,

  我用了个换底公式,好像库里是没有以2为底的函数,只有自然对数和常用对数

  具体是为什么这么列式,我觉得真的没啥好说的。。。

  3.在何时终止当前行枚举的那层循环

  

  注意,这里的last我有用的,所以最好不要写在循环的第二个分号里(当然这么写再稍微判断一下也是可以的)

  4.如何枚举上一层状态,到哪结束

  这就是last的意义——记录上一层到q的第多少个,也就是有多少种状态

  当然这里的last你看我整个循环,其实他是有可能从上面for的第二个分号出去的,所以开始last要赋成q_cnt而不是0,-1之类无意义的值,防止last还没被赋值就跳出来

  这次真没了

代码:

#include<cstdio>
#include<cmath>
using namespace std; #define ll long long const int maxk=2e1+;
const int mod=1e9+;
const int maxn=1e5+; int dp[maxn][maxk];
int q[maxn]; int pd(int x)
{
if(x&(x<<)||x&(x>>)) return ;
return ;
} int pdd(int x,int y)
{
if(x&y) return ;
return ;
} int main()
{
int n;
scanf("%d",&n);
ll ji=;
int hh=(int)(log(n)/log())+;
int q_cnt=;
for(int i=;i<<<hh;++i) if(pd(i)) q[q_cnt++]=i;
for(int i=;i<=n;++i) if(i%&&i%)
{
int last=q_cnt,p=;
for(int j=i;j<=n;j*=,++p)
{
int now=(int)(log(n/j)/log())+1;
for(int k=;k<q_cnt;++k)
{
if(q[k]>=<<now)
{
last=k;
break;
}
if(!p) dp[k][p]=;
else
{
int nowans=;
for(int t=;t<last;++t) if(pdd(q[k],q[t]))
{
nowans+=dp[t][p-];
if(nowans>=mod) nowans-=mod;
}
dp[k][p]=nowans;
}
}
}
int ans=;
for(int j=;j<last;++j)
{
ans+=dp[j][p-];
if(ans>=mod) ans-=mod;
}
ji*=(ll)ans,ji%=(ll)mod;
}
printf("%lld",ji);
return ;
}

J集合选数的更多相关文章

  1. 【BZOJ-2732】集合选数 状压DP (思路题)

    2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1070  Solved: 623[Submit][Statu ...

  2. bzoj 2734: [HNOI2012]集合选数 状压DP

    2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 560  Solved: 321[Submit][Status ...

  3. 【BZOJ2734】【HNOI2012】集合选数(状态压缩,动态规划)

    [BZOJ2734][HNOI2012]集合选数(状态压缩,动态规划) 题面 Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所 ...

  4. BZOJ_2734_[HNOI2012]集合选数_构造+状压DP

    BZOJ_2734_[HNOI2012]集合选数_构造+状压DP 题意:<集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x ...

  5. 2734: [HNOI2012]集合选数

    2734: [HNOI2012]集合选数 链接 分析: 转化一下题意. 1 3 9 27... 2 6 18 54... 4 12 36 108... 8 24 72 216... ... 写成这样的 ...

  6. [HNOI2012]集合选数 --- 状压DP

    [HNOI2012]集合选数 题目描述 <集合论与图论>这门课程有一道作业题,要求同学们求出\({1,2,3,4,5}\)的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x ...

  7. 【BZOJ-2734】集合选数 状压DP (思路题)

    2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1070  Solved: 623[Submit][Statu ...

  8. bzoj2734【HNOI2012】集合选数

    2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 831  Solved: 487 [Submit][Stat ...

  9. 状压DP之集合选数

    题目 [HNOI2012]集合选数 <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不 ...

随机推荐

  1. HTTPS工作流程

    HTTPS工作流程 RSA算法 RSA的密钥分成两个部分: PublicKey 加密数据 验证签名 不能解密 任何人都可以获得 Private Key 数据签名(摘要算法) 解密 加密(不用此功能) ...

  2. Docker-CentOS系统安装Docker

    上一节,我们介绍了安装虚拟机及操作系统,本文再详细描述安装docker的命令. 前提条件 虚拟机系统:CentOS,并且虚拟机能连通外网. 另外,虚拟机最好配置上阿里的镜像源,点此链接,进入cento ...

  3. 设计模式中巧记I/O

    一.I/O 1. I/O操作中的设计模式 概要 以设计模式角度,自顶向下理解I/O源码结构 理解字节与字符的关系 1.1 装饰者模式(输入流为例) 背景:通过继承扩展对象耦合度高,使用装饰者扩展可以在 ...

  4. 解决同层hover事件重叠闪烁问题

    完整代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  5. day5 作业

    tips:作业 作业: 0.分别画出下面两个列表在内存中是如何存放的 l1=[11,22,[333,444]] l2=[11,22,[33,{'name':'egon','age':18}]] ''' ...

  6. git多人协作操作流程

    git协作工作流程 git checkout work 自己工作分支工作 git commit -a -m ''自己工作分支提交 git checkout master 切换到主分支 git pull ...

  7. 从零开始学AB测试:基础篇

    什么是AB测试? 通俗点理解,AB测试就是比较两个东西好坏的一套方法,这种A和B的比较在我们的生活和人生中非常常见,所以不难理解.具体到AB测试这个概念,它和我们比较哪个梨更大.比较哪个美女更漂亮.比 ...

  8. 【题解】P2831 愤怒的小鸟 - 状压dp

    P2831愤怒的小鸟 题目描述 \(Kiana\) 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 \((0,0)\) 处,每次 \(Kiana\) 可以 ...

  9. Java 反射 -- 获取泛型类型

    先写一个类: public class Demo03 { public void test01(Map<String, User> map, List<User> list) ...

  10. 9个小技巧让你的 if else看起来更优雅

    if else 是我们写代码时,使用频率最高的关键词之一,然而有时过多的 if else 会让我们感到脑壳疼,例如下面这个伪代码: 是不是很奔溃?虽然他是伪代码,并且看起来也很夸张,但在现实中,当我们 ...