当前位置: 首页 > news >正文

枚举子集

枚举子集

发现自己经常记不住这个怎么写,就来写篇题解吧。

首先对于一个 \(n\) 位二进制数 \(x\),求二进制位上都是 \(x\) 的子集的数有哪些,

比如:101的子集有100、001、000。

然后这个东西如果直接 \(2^n\) 次枚举的话,复杂度就爆炸了。

所以可以用一个很厉害的东西,

代码长这样:

for(int i=(x-1)&x;i;i=(i-1)&x)

这个 \(i\) 直接就是枚举出来的子集了。

这个为啥是对的呢?

我的理解是,你普通枚举 \(i\)-- 了之后,可能出现一个地方 \(i\) 有个 \(1\) 但是 \(x\)\(0\)

所以你把 \(i\)\(x\) 与一下,来把这个 \(1\) 消掉就好了。

如果只求一个 \(x\) 的所有子集,那复杂度就是 \(2^n\)

但是如果求 \(1\sim 2^n-1\) 中的数字的所有子集,那这个的复杂度就是 \(3^n\)

(好像是用什么二项式定理求出来的,但是蒟蒻不会qwq)

例题

P3773 [CTSC2017] 吉夫特

发现组合数可以用 \(lucas\) 分解一下,相当于对于 \(2\le i \le k\)\(a_{b_i}\) 都要是 \(a_{b_{i-1}}\) 二进制位上的子集。

直接 \(dp\),设 \(f[i]\) 表示以 \(i\) 结尾的合法子序列个数。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10,mod=1e9+7;
int n,ans,f[N];
int main()
{scanf("%d",&n);for(int i=1,x;i<=n;i++){scanf("%d",&x);for(int j=(x-1)&x;j;j=(j-1)&x)f[j]=(f[j]+f[x]+1)%mod;ans=(ans+f[x])%mod;}printf("%d",ans);return 0;
}
http://www.sczhlp.com/news/129698/

相关文章:

  • cv-css 快捷方式,将指定节点的计算样式获取下拉 获取tailwind网页样式成原生样式
  • 国内包装设计网站浏阳企业网站建设
  • 邯郸做移动网站多少钱现在做网站怎么样
  • 济南做企业网站公司专升本需要考些什么科目
  • 网站开发需要后台吗高新区做网站的公司
  • 溧阳市建设局网站北京海淀网站制作公司
  • 电子商务运营网站郴州网站设计
  • 免费网站怎么注册哪儿有网络推广培训
  • 企业网站建设需注意什么一般网站建设需求有哪些方面
  • 网站设计网站源码广州万户网络科技有限公司
  • 网站建设推广服务合同wordpress 获取ip
  • 网站开发实例模板全国免费分类信息发布平台
  • 网站怎么做免费seo搜索引擎哪家公司的网好
  • 前端电商网站开发周期百丽优购物官方网站
  • 如何开发网站软件app软件景观规划设计公司
  • Avalonia 学习笔记07. Control Themes(控件主题)
  • 廊坊网站关键词优化论文 网站建设可行性
  • WordPress电影公司网站主题专业站
  • 长沙本土网站制作公司用外链技术做视频网站
  • 国产手机做系统下载网站wordpress最新列表页
  • xp系统做局域网内网站明光网站建设
  • 大连网站建设仟亿科技网络建设公司哪家好
  • 住房和城乡建设部网站第九批app推广渠道有哪些
  • 林和西网站建设做中文网站公司
  • 电子商务网站建设开发文档网站做程序
  • 龙泉驿建设局网站一级造价师注册查询系统平台入口
  • matter 协议的架构;
  • matter 协议解析;
  • 9月23日
  • Nordic 的支持对Matter 协议的支持;