J集合选数
题意:求出{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集合选数的更多相关文章
- 【BZOJ-2732】集合选数 状压DP (思路题)
2734: [HNOI2012]集合选数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1070 Solved: 623[Submit][Statu ...
- bzoj 2734: [HNOI2012]集合选数 状压DP
2734: [HNOI2012]集合选数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 560 Solved: 321[Submit][Status ...
- 【BZOJ2734】【HNOI2012】集合选数(状态压缩,动态规划)
[BZOJ2734][HNOI2012]集合选数(状态压缩,动态规划) 题面 Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所 ...
- BZOJ_2734_[HNOI2012]集合选数_构造+状压DP
BZOJ_2734_[HNOI2012]集合选数_构造+状压DP 题意:<集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x ...
- 2734: [HNOI2012]集合选数
2734: [HNOI2012]集合选数 链接 分析: 转化一下题意. 1 3 9 27... 2 6 18 54... 4 12 36 108... 8 24 72 216... ... 写成这样的 ...
- [HNOI2012]集合选数 --- 状压DP
[HNOI2012]集合选数 题目描述 <集合论与图论>这门课程有一道作业题,要求同学们求出\({1,2,3,4,5}\)的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x ...
- 【BZOJ-2734】集合选数 状压DP (思路题)
2734: [HNOI2012]集合选数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1070 Solved: 623[Submit][Statu ...
- bzoj2734【HNOI2012】集合选数
2734: [HNOI2012]集合选数 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 831 Solved: 487 [Submit][Stat ...
- 状压DP之集合选数
题目 [HNOI2012]集合选数 <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不 ...
随机推荐
- 加锁的位置 (eq:map<key,map<>> 双集合 怎么 只加锁 在用到的对象位置,而不是把整个集合锁住)
比如上边的map里套map 定义变量为data,例如组队副本 npc 为1 下有众多房间 即Map<1,<roomId,room>> ,处于多线程下,一个线程在 npc为1的下 ...
- Redis之ziplist源码分析
一.ziplist简介 从上一篇分析我们知道quicklist的底层存储使用了ziplist(压缩列表),由于压缩列表本身也有不少内容,所以重新开了一篇,在正式源码之前,还是先看下ziplist的特点 ...
- 记录:如何使用ASP.NET Core和EnityFramework Core实现服务和数据分离
前情提要: 现有一个网站框架,包括主体项目WebApp一个,包含 IIdentityUser 接口的基架项目 A.用于处理用户身份验证的服务 AuthenticationService 位于命名空间B ...
- DES加密解密算法C++实现
DES加密算法并不难,是由一些简单的变换得来的,难的是要有足够的耐心.蒟蒻并不想说自己用了多久才把代码写好的. 代码: 我真的太难了QAQ #include<iostream> using ...
- 如何快速地恢复你的win10
win10清单 这份List不会介绍如何安装系统,而是当面对一个新系统,如何最快的搭建,或者说恢复到一个生产力环境. 必备习惯 备份软件安装包和常用内容上云是高效恢复的两点关键. 备份软件安装包 我的 ...
- 面试官:你对Redis缓存了解吗?面对这11道面试题你是否有很多问号?
前言 关于Redis的知识,总结了一个脑图分享给大家 1.在项目中缓存是如何使用的?为什么要用缓存?缓存使用不当会造成什么后果? 面试官心理分析 这个问题,互联网公司必问,要是一个人连缓存都不太清楚, ...
- LeetCode 面试题56 - I. 数组中数字出现的次数 | Python
面试题56 - I. 数组中数字出现的次数 题目 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). ...
- memcache雪崩
缓存雪崩一般是由某个缓存节点失效,导致其他节点的缓存命中率下降, 缓存中缺失的数据(memcache经典场景,当有一个客户端的服务请求过来的时候,首先去查memcache,memcache里面是否缓存 ...
- python学习20之面向对象编程高级
'''''''''1.动态绑定:对于一个类,我们可以对它的实例动态绑定新的属性或方法.为了使所有的实例均可以使用动态绑定的属性和方法,我们也可以采用对类直接动态绑定'''class Student() ...
- NGINX反向代理,后端服务器获取真实IP
一般使用中间件做一个反向代理后,后端的web服务器是无法获取到真实的IP地址. 但是生产上,这又是不允许的,那么怎么解决? 1.在NGINX反向代理服务器上进行修改 2.修改后端web服务器配置文件 ...