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

【学习笔记】子集DP

背景

有一类问题和子集有关。
给你一个集合 S S S,令 T T T S S S 的超集,也就是 S S S 所有子集的集合,求 T T T 中所有元素的和。

暴力1

先预处理子集的元素和 A i A_i Ai,再枚举子集。

for(int s=0; s<(1<<n); s++)for(int i=0; i<(1<<n); i++)if(s&i) f[s]+=A[i];

时间复杂度 O ( n 4 ) O(n^4) O(n4)

暴力2

其实枚举子集有个小 trick

for(int s=0; s<(1<<n); s++)for(int i=s; i>0; i=(i-1)&s)f[s]+=A[i];

由二项式定理,时间复杂度为 O ( 3 n ) O(3^n) O(3n)

子集DP

g s , i g_{s,i} gs,i 为状态为 s s s,只考虑后 i i i 位转移的答案。
那么转移就是

g s , i = { g s , i − 1 s & ( 1 < < i ) = 0 g s , i − 1 + g s ⨁ ( 1 < < i ) , i − 1 o t h e r w i s e g_{s,i} = \begin{cases} g_{s,i-1} & s\&(1<<i)=0 \\g_{s,i-1} +g_{s\bigoplus(1<<i),i-1}&otherwise\end{cases} gs,i={gs,i1gs,i1+gs(1<<i),i1s&(1<<i)=0otherwise
这样可以做到不重不漏的转移。
推荐一篇blog,非常形象:https://www.cnblogs.com/maple276/p/17975253

可以发现,这个转移只和上一层有关,所以第二维是可以省略的。

前缀和(子集向超集转移)
for(int i=0; i<n; i++)
{for(int s=0; s<(1<<n); s++){if(s&_2)(f[s]+=f[s^_2])%(mod-1);}_2<<=1;
}
后缀和(超集向子集转移)
for(int i=0; i<n; i++)
{for(int s=0; s<(1<<n); s++){if(!(s&_2))(f[s]+=f[s^_2])%(mod-1);}_2<<=1;
}
差分
//后缀差分
for(int i=0; i<20; i++)
{for(int s=0; s<S; s++){if(!(s&_2))(f[s]-=f[s^_2])%=mod;}_2<<=1;
}

例题

CF165E

定义 x x x y y y 相容为 x & y = 0 x\&y=0 x&y=0,给你一个序列 A A A,对于每个元素,在 A A A 中找到和它相容的元素。 ∣ A ∣ ≤ 1 0 6 , A i ≤ 4 × 1 0 6 |A|\leq 10^6,A_i\leq 4\times 10^6 A106,Ai4×106

思路

x & y = 0 x\&y=0 x&y=0 等价于 x ˜ & y = y \~x\&y=y x˜&y=y,那么只需要对 A A A做类似前缀和的操作,加法改成覆盖即可。

代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int S=1<<22;
void O_o()
{int n;cin>>n;vector<int> f(S,-1),a(n+1);for(int i=1; i<=n; i++){cin>>a[i];f[a[i]]=a[i];}int _2=1;for(int i=0; i<=21; i++){for(int s=0; s<S; s++){if(!(s&_2)) continue;if(f[s^_2]!=-1)f[s]=f[s^_2];}_2<<=1;}int t=S-1;for(int i=1; i<=n; i++){cout<<f[t^a[i]]<<" ";}cout<<"\n";
}
signed main()
{ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cout<<fixed<<setprecision(2);int T=1;
//	cin>>T;while(T--){O_o();}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • nginx代理服务配置,基于http协议-Linux(CentOS)
  • JavaEE - Spring Boot 简介
  • MATLAB-bode图编程
  • 本地连接远程阿里云K8S
  • OpenCV车牌识别技术详解
  • 【数据结构之C语言实现动态顺序表】
  • “/usr/local/nginx/logs/nginx.pid“ failed (2: No such file or directory)问题
  • k8s中的重启策略
  • 视觉SLAM第二讲
  • 【03】Java虚拟机是如何加载Java类的
  • AttributeError: module ‘selenium.webdriver‘ has no attribute ‘PhantomJS‘
  • QT 关于QTableWidget的常规使用
  • Postman测试工具详细解读
  • 如何将整个运行环境打包成docker
  • 每日一知识点 - Java Lambda 表达式
  • [PHP内核探索]PHP中的哈希表
  • #Java异常处理
  • (三)从jvm层面了解线程的启动和停止
  • 【347天】每日项目总结系列085(2018.01.18)
  • 【附node操作实例】redis简明入门系列—字符串类型
  • css系列之关于字体的事
  • JavaScript服务器推送技术之 WebSocket
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • vue--为什么data属性必须是一个函数
  • Wamp集成环境 添加PHP的新版本
  • Zepto.js源码学习之二
  • 阿里云应用高可用服务公测发布
  • 从tcpdump抓包看TCP/IP协议
  • 如何编写一个可升级的智能合约
  • 三栏布局总结
  • 一个JAVA程序员成长之路分享
  • Hibernate主键生成策略及选择
  • raise 与 raise ... from 的区别
  • 阿里云服务器购买完整流程
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • (10)STL算法之搜索(二) 二分查找
  • (libusb) usb口自动刷新
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (分布式缓存)Redis哨兵
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (算法)Travel Information Center
  • (已解决)Bootstrap精美弹出框模态框modal,实现js向modal传递数据
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (转)visual stdio 书签功能介绍
  • (转)用.Net的File控件上传文件的解决方案
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • (转载)从 Java 代码到 Java 堆
  • **PHP二维数组遍历时同时赋值
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .NET C# 操作Neo4j图数据库
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .NET/C# 使窗口永不获得焦点
  • .net6使用Sejil可视化日志