SOS DP学习笔记
Sum over Subsets(SOS) DP
一、引入
给出一个长度为\(2^n\)的数组\(A\),对于每一个\(mask< 2^n\)要求计算出\(f[mask]=\sum_{sub\in mask}A[sub]\)
(其中\(sub\in mask\)表示\(sub\&mask=sub\))
二、解法
1.暴力
for(int mask = 0; mask < (1<<n); mask++)
for(int sub = 0; sub <= mask; sub++)
if((sub & mask) == sub)
f[mask] += A[sub];
根据定义直接做,枚举所有小于\(mask\)的集合,判断\(sub\)是否是\(mask\)的子集
复杂度\(O(4^n)\)
2.子集枚举
for(int mask = 0; mask < (1<<n); mask++){
for(int sub = mask; ; sub = mask&(sub-1)){
f[mask] += A[sub];
if(!sub) break;
}
}
子集枚举优化之后
总复杂度是\(\sum_{m=0}^{n}C(n,m)\cdot 2^m = \sum_{m=0}^{n}C(n,m)\cdot 2^m\cdot 1^{n-m}=(1+2)^n\)
复杂度\(O(3^n)\)
3.SOSDP
考虑在计算当前的状态的\(f[mask]\)的时候,能否利用之前计算的结果来优化复杂度,并且不会重复计算
那就要定义新的状态:\(f[mask][bit]\)表示对于集合\(mask\),在子集\(sub\)和\(mask\)只有最后\(bit\)位存在不同的情况下的答案
可以发现\(f[mask][bit]= \begin{cases} A[mask] & bit=-1 \\ f[mask][bit-1] & mask\&(1<<bit)=0 \\ f[mask][bit-1]+f[mask \bigoplus (1<<bit)][bit-1] & mask\&(1<<bit)!=0 \end{cases}\)
当前位是\(1\)的情况下有两个分支,这个位置是\(1\)或者\(0\),并且从只改变之后的位的状态转移过来,能保证不重复
当前位是\(0\)的情况下这个位不能改变,所以只能选这位是\(0\)的之后的状态转换过来
空间压缩一下,代码如下
for(int mask = 0; mask < (1<<n); mask++) f[mask] = A[mask];
for(int bit = 0; bit < n; bit++)
for(int mask = 0; mask < (1<<n); mask++)
if(mask&(1<<bit)) f[mask] += f[mask^(1<<bit)];
复杂度\(O(n2^n)\)
考虑一下如何计算\(f[sub]=\sum_{sub \in mask} A[mask]\)
可以发现把所有集合取反,\(f[\overline{sub}] = \sum_{\overline{mask}\in \overline{sub}}A[\overline{mask}]\)
就相当于把\(0\)变成\(1\)来处理,代码基本相同
for(int mask = 0; mask < (1<<n); mask++) f[mask] = A[mask];
for(int bit = 0; bit < n; bit++)
for(int mask = 0; mask < (1<<n); mask++)
if(!(mask&(1<<bit))) f[mask] += f[mask^(1<<bit)]; // 只有这里的if改了
三、例题
参考CF博客
SOS DP学习笔记的更多相关文章
- 数位DP学习笔记
数位DP学习笔记 什么是数位DP? 数位DP比较经典的题目是在数字Li和Ri之间求有多少个满足X性质的数,显然对于所有的题目都可以这样得到一些暴力的分数 我们称之为朴素算法: for(int i=l_ ...
- DP学习笔记
DP学习笔记 可是记下来有什么用呢?我又不会 笨蛋你以后就会了 完全背包问题 先理解初始的DP方程: void solve() { for(int i=0;i<;i++) for(int j=0 ...
- 树形DP 学习笔记
树形DP学习笔记 ps: 本文内容与蓝书一致 树的重心 概念: 一颗树中的一个节点其最大子树的节点树最小 解法:对与每个节点求他儿子的\(size\) ,上方子树的节点个数为\(n-size_u\) ...
- 斜率优化DP学习笔记
先摆上学习的文章: orzzz:斜率优化dp学习 Accept:斜率优化DP 感谢dalao们的讲解,还是十分清晰的 斜率优化$DP$的本质是,通过转移的一些性质,避免枚举地得到最优转移 经典题:HD ...
- 动态 DP 学习笔记
不得不承认,去年提高组 D2T3 对动态 DP 起到了良好的普及效果. 动态 DP 主要用于解决一类问题.这类问题一般原本都是较为简单的树上 DP 问题,但是被套上了丧心病狂的修改点权的操作.举个例子 ...
- [总结] 动态DP学习笔记
学习了一下动态DP 问题的来源: 给定一棵 \(n\) 个节点的树,点有点权,有 \(m\) 次修改单点点权的操作,回答每次操作之后的最大带权独立集大小. 首先一个显然的 \(O(nm)\) 的做法就 ...
- 插头DP学习笔记——从入门到……????
我们今天来学习插头DP??? BZOJ 2595:[Wc2008]游览计划 Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该 ...
- 树形$dp$学习笔记
今天学习了树形\(dp\),一开始浏览各大\(blog\),发现都\(TM\)是题,连个入门的\(blog\)都没有,体验极差.所以我立志要写一篇可以让初学树形\(dp\)的童鞋快速入门. 树形\(d ...
- 斜率优化dp学习笔记 洛谷P3915[HNOI2008]玩具装箱toy
本文为原创??? 作者写这篇文章的时候刚刚初一毕业…… 如有错误请各位大佬指正 从例题入手 洛谷P3915[HNOI2008]玩具装箱toy Step0:读题 Q:暴力? 如果您学习过dp 不难推出d ...
随机推荐
- SAAS云平台搭建札记: (三) AntDesign + .Net Core WebAPI权限控制、动态菜单的生成
我们知道,当下最火的前端框架,非蚂蚁金服的AntDesign莫属,这个框架不仅在国内非常有名,在国外GitHub上React前端框架也排名第一.而且这个框架涵盖了React.Vue.Angular等多 ...
- Nginx集成Naxsi防火墙
前言 因工作原因,接触到了WAF,今天部署了一下Naxsi,记录一下 GitHub 正文 环境 Centos 7 下载 更新yum yum update -y 安装必要依赖 yum install g ...
- 剑指 Offer 16. 数值的整数次方
实现函数double Power(double base, int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题. 来源:力扣(LeetCode) 链接 ...
- Java开发手册之安全规约
1.用户敏感数据禁止直接展示,必须对展示数据进行脱敏.例如手机号.银行卡号等,中间要用*隐藏. 2.发贴.评论.发送即时消息等用户生成内容的场景必须实现防刷.文本内容违禁词过滤等风控策略,一般是用验证 ...
- 【Linux】NFS相关小问题
NFS一些小问题: 1. 由于实验环境中,给了rw权限,但是执行的时候,还是提示Permission denied 于是查看nfs服务端,查看/etc/exports文件是否配置有问题 网上很多人配置 ...
- kubernets集群的安全防护(下)
一 集群角色以及集群角色绑定 1.1 前面我们提到过角色以及角色绑定,那么现在为什么会出现集群级别的角色以及角色绑定,作用有如下所示 我们如果需要在所有的命名的空间创建某个角色或者角色绑定的时候 ...
- 使用jib-maven-plugin将Spring Boot项目发布为Docker镜像
目录 介绍 使用 总结 介绍 将spring boot(cloud)项目发布到docker环境作为镜像,一般常用的一个是com.spotify的docker-maven-plugin这个maven插件 ...
- 如何在 Blazor WebAssembly中 使用 功能开关
微软Azure 团队开发的 功能管理 (Feature Management) 包 Microsoft.FeatureManagement可用于实现 功能开关,可以通过 功能开关 特性动态的改变应用程 ...
- 阅读lodash源码之旅数组方法篇-compact和concat
鲁迅说过:只有阅读过优秀库源码的人,才能配的上是真正的勇士. compact 创建一个新数组,包含原数组中所有的非假值元素.例如false, null,0, "", undefin ...
- 【MYSQL】DDL语句
介绍:DDL语句,即数据定义语句,定义了不同的数据段,数据库表.表.列.索引等数据库对象:例如,create.drop.alter 适用对象:一般是由数据库管理员DBA使用 1.连接数据库 mysql ...