题意:求出{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. 统计分析_集中趋势and离散程度

    1.数组的集中趋势-如何定义数组的中心 1.1 常用几下几个指标来描述一个数组的集中趋势 均值-算术平均数 . 中位数-将数组升序或降序排列后,位于中间的数. 众数-数组中出现最多的数. 1.2 指标 ...

  2. Git常用指令整理(Git Cheat Sheet)

    [Toc] 1. 创建 复制一个已创建的仓库:git clone ssh://user@domain.com/repo.git 创建一个新的本地仓库:git init 2. 本地修改 显示工作路径下已 ...

  3. jvm入门及理解(三)——运行时数据区(程序计数器+本地方法栈)

    一.内存与线程 内存: 内存是非常重要的系统资源,是硬盘和cpu的中间仓库及桥梁,承载着操作系统和应用程序的实时运行.JVM内存布局规定了JAVA在运行过程中内存申请.分配.管理的策略,保证了JVM的 ...

  4. 《深入理解 Java 虚拟机》读书笔记:垃圾收集器与内存分配策略

    正文 垃圾收集器关注的是 Java 堆和方法区,因为这部分内存的分配和回收是动态的.只有在程序处于运行期间时才能知道会创建哪些对象,也才能知道需要多少内存. 虚拟机栈和本地方法栈则不需要过多考虑回收的 ...

  5. coding++:都说新的Arraylist 扩容是(1.5倍+1) 看了1.8的源代码发现不是这么回事

     都说新的Arraylist 扩容是(1.5倍+1) 看了1.8的源代码发现不是这么回事 就用下面这段代码在jdk的三个版本运行看了下效果: import java.lang.reflect.Fiel ...

  6. 一个有关 scala 编程语言 的博客

    http://www.cnblogs.com/superjt/category/312683.html

  7. 使用Jmeter测试java请求

    1.性能测试过程中,有时候开发想对JAVA代码进行性能测试,Jmeter是支持对Java请求进行性能测试,但是需要自己开发.打包好要测试的代码,就能在Java请求中对该java方法进行性能测试2.本文 ...

  8. 绕过XSS过滤姿势总结

    0x01 弹窗关键字检测绕过 基本WAF都针对常用的弹窗函数做了拦截,如alert().prompt().confirm(),另外还有代码执行函数eval(),想要绕过去也比较简单,我们以alert( ...

  9. [PHP][mysql] 需要知道的那些事

    就是想总结一下自己不会的! sql: 1.在SQL语句中出现AS,是起别名的意思! 例子:select a.* from table_1 as a就是给table_1起个别名叫a,因此前面就可以使用a ...

  10. SMTP发邮件(直接可用)实例

    string file = "邮件测试.txt";//放在Debug下的一个txt文件. MailAddress from = new MailAddress("自己的邮 ...