状态压缩动态规划

news/2025/1/10 22:17:47/文章来源:https://www.cnblogs.com/zhone-lb/p/18522197

\(3^n\)枚举子集

状压DP中相当重要的技巧(虽然后位有FWT,FMT替代,但不是都能代)

for(int i = x; i; i = (i - 1) & x) {
// i 就是 x 的子集
}

题目

P6622 [省选联考 2020 A/B 卷] 信号传递

看数据范围,\(m \le 23\),且不同分数段增长很慢,表明会有\(O(2^m)\)的做法,考虑状压或搜索剪枝

但是题目要求的是排列的贡献,直接状压不可行,需要转化为与顺序无关的情况

观察到\(n \le 10^5\),表明对\(S\)序列要有很快的统计方式

关键转换:发现\(s[i-1]\)\(s[i]\)之间的转移只会有\(m^2\)种,预处理出\(s[]\)中每种的转移次数,那么此时数字\(i\)和数字\(j\)(设重排列后\(i\)\(j\)前面)之间的贡献为:

\[W_{i,j}=cnt[i][j]*(pos[j]-pos[i])+k*cnt[j][i]*(pos[j]+pos[i]) \]

\[=pos[j]*(cnt[i][j]+k*cnt[j][i])+pos[i]*(k*cnt[j][i]-cnt[i][j]) \]

此时\(i,j\)的贡献分为两部分,分别仅与\(pos[i],pos[j]\)相关,可以分别统计;\(pos[i],pos[j]\)可以在枚举位置时分别获取,而剩下部分仅与\(i,j\)的相对位置有关,状压可以做到

方程很好推,时间复杂度\(O(m^2*2^m)\),过不了后40分

考虑\(i\)插入时对\(S\)的影响是一定的,可以在dp外预处理出\(g[i][S]\)(想想如何做到\(O(m*2^m)\)),空间又炸了

接下来就是空间优化了 link

反思

被djy薄纱了,难受

考试时思路走错了,以为是直接替换\(s[]\),然后关键的预处理没想到,之后应该就是自然的思路了

关键在于看到数据范围就朝着状压的方向走,不断尝试消除排列的影响

P3959 [NOIP2017 提高组] 宝藏

思路来源

读题,一眼看出状态,但发现缺少层数,无法转移

考虑强制限定层数,所有新加点强制对上一层连边,而不是任意层

感性理解该状态转移完全

p.s. 开始考虑强制选定前一个点,发现这样子树状态还要上传,有后效性,没想到是按层转移(悲

P7519 [省选联考 2021 A/B 卷] 滚榜

最朴素方程非常好列,把状态、总和,前一个数,前一个数取的值全部放入方程即可,但是没有穷举+贪心快

重要性质:由于\(b[i]\)单调不降,一个常见(?)的思路就是考虑横向统计,如图

这说明我们不需要考虑前一个\(b[]\)取了多少,因为当前的\(b[]\)就是基于前面的\(b[]\),相当于把往后的分值同时向上顶了\(b[i-1]\),此时想要方案合法,只需考虑\(a[i]\)\(a[i-1]\)之间差了多少即可,类似差分思想

p.s. 卡常技巧:把大循环的int变为宏会更快

根号分治

做题时,如果遇到与质因数有关的状压DP,考虑根号分治

原理:我们约定大于\(\sqrt n\)的数为大质数,则\(\forall x \in [2,n]\),都有\(x\)的质因数中,要么没有大质数,要么有且仅有一个

这样我们就在\(x\)唯一对应了一个大质数,利用该性质,可以解决此类问题

P2150 [NOI2015] 寿司晚宴

朴素方程略

很明显,对于一个大质数\(x\),要么小G取,要么小W取,要么都不取,那么把所有对应此大质数\(x\)的数放在一起,分\(g1[][]\)\(g2[][]\)分别统计\(x\)被小G取、小W取的方案数,再合并至\(f[][]\)中即可

p.s. 注意\(g1\)\(g2\)会有重复计数(都不取),记得减掉

P8292 [省选联考 2022] 卡牌

这道题有两种做法:FWT和容斥

题解都说样例提示了正难则反,但是我觉得FWT更自然……

做法1:暴力状压+FWT优化枚举子集

先根号分治,设\(f[i][S]\)为大质数为\(i\),小质数状态为\(S\)

对大质数不同的数分开跑\(f[i][]\)

那么最后合并答案\(f_0[S]\leftarrow \sum_{i|j=S}f_0[i]*f_k[j]\),可以用\(FWT\)优化

做法2:容斥

看看题目要求的是什么,不要容斥错了

其实第一眼发现\(s_i\le30\)的状压是可以直接转移的,问题在于统计是枚举,考虑在这里优化

题目求的是质数集至少\(S\),子集反演直接pass

考虑容斥中常见的钦定大法,(不能钦定\(x\)一定出现,因为这样得到的就是题目求的质数集至少为\(S\)的方案数,绕一圈又回来了)

我们考虑钦定\(g[S]\)\(S\)一定不出现的方案数,则\(f(S)=\sum_{T\subseteq S}(-1)^{|T|}g(T)\)

此时\(g(T)\)的贡献变得更简单:对于质数集为\(P\)的数\(x\),若\(P\cap T=\varnothing\),则\(x\)可被\(g(T)\)统计到,则\(g(T)=2^{cnt[T]}\)

考虑大质数时也一样,只不过对于要求选取的大质数必须选一个,即\(g(T)=2^{cnt[T]}-1\),最后根据乘法原理把每个大质数的\(g\)乘起来即可

技巧:如果每次都把大质数的\(g\)全部累乘,那时间复杂度就会有\(O(m|S|\cdot 2^{14})\)\(S\)\(2000\)以内的质数集),无法承受;考虑只有给定的大质数才有必须选的需求,对于其它大质数,直接\(\sum g(T)=\sum2^{cnt[T]}=2^{\sum cnt[T]}\)计算即可,复杂度\(O(2^{14}\cdot \sum c)\)

快速沃尔什变换(FWT)

求解\(\displaystyle C_i=\sum_{j\oplus k=i}A_jB_k\),其中\(\oplus\)\(or,and,xor\)

FWT类似于FFT,是基于反演优化的(FWT更直观一点),实际上就是找一个式子\(FWT[A_i]=\sum A_j\),使得\(FWT[C_i]\)恰好等于\(FWT[A_i]*FWT[B_i]\),从而用类似多项式点值表示的方法优化卷积

或卷积

这里找到的式子为\(\displaystyle FWT[A_i]=\sum_{j|i=i}A_j\),下面是证明

\(\displaystyle FWT[A_i]*FWT[B_i]=(\sum_{j|i=i}A_j)*(\sum_{k|i=i}B_k) =\sum_{(j|k)|i=i}A_jB_k=FWT[C_i]\)

接下来就是高效处理出\(FWT[A]\)了,高维前缀和可以做到,不过考虑类似FFT的分治做法,在合并\([l,mid],[mid+1,r]\)时,有公式\(FWT[l\sim r]=merge(FWT[l\sim mid],FWT[l\sim mid]+FWT[mid+1\sim r])\)

转成二进制形式,\(A_0\)为当前最高位为\(0\)\(A_1\)为当前最高位为\(1\),有

\(FWT[A]=merge(FWT[A_0],FWT[A_0]+FWT[A_1])\)

还原数组时减回来即可

\(IFWT[A]=merge(IFWT[A_0],IFWT[A_0]-IFWT[A_1])\)

与卷积

\(FWT[A]=merge(FWT[A_0]+FWT[A_1],FWT[A_1])\)

\(IFWT[A]=merge(IFWT[A_0]-IFWT[A_1],IFWT[A_1])\)

异或卷积

\(FWT[A]=merge(FWT[A_0]+FWT[A_1],FWT[A_0]-FWT[A_1])\)

\(\displaystyle IFWT[A]=merge(\frac {IFWT[A_0]+IFWT[A_1]} 2,\frac {IFWT[A_0]-IFWT[A_1]} 2)\)

子集卷积

即求\(\displaystyle h(S)=\sum_{i|j=S,i\&j=\emptyset}f(i)*g(j)\)

子集反演

当方程\(f[S]\)难以快速统计转移时,考虑弱化它,然后容斥

具体地,设\(f[S]\)为状态集恰好\(S\)时的方案数,\(g[S]\)为状态集至多\(S\)时的方案数

即只能从\(S\)中取数,但不要求全部取完,此时\(g[S]\)的优势在于不用枚举子集,直接传\(S\)即可

此时有容斥:\(f(S)=\sum_{T\subseteq S}(-1)^{|S|-|T|}g(T)\)

证明略

P3349 [ZJOI2016]小星星

首先得想到枚举子集,向儿子递归转移,时间复杂度\(O(n^3\cdot3^n)\)

然后考虑把恰好为\(S\)换成至多为\(S\),做子集反演,每次转移直接将\(S\)下传,将答案容斥即可

注意这里有个技巧:不需要使得编号对应不重(即树上两个点可能对应图上的同一个点),因为对于答案\(f[111...]\),需要\(n\)个点恰好取满,这种情况必不会重

\(p.s.\) 常数优化:提取每次\(S\)的点集,还有不把\(i\)分配的编号\(q[i]\)放入递归参数(亲测快\(5\)倍,可能是开栈相对循环太慢了)

C. 拼凑数字

给你\(n\)个数字,你需要将它们拼成一个\(n\)位整数 ,使得在保证\(n\)\(k\)取模的结果最大的前提下, 尽可能大。\(n\le 24,k\le 80\)

首先得想到朴素状压(逆天,我考时没想到

\(f[S][i]\)为取数状态为\(S\),余数为\(i\)的最大数,转移即可

然后想到每个数只能是\(1\thicksim 9\),记录每种数字用了几次即可

通过计算可知,状态数最多为\(1.1\times 10^5\),可以接受

但是对于非01串的状压,可能需要一点优化

技巧

P3813 [FJOI2017]矩阵填数

常见思路:最大值为\(v\)方案数\(=\)最大值\(\le v\)的方案数\(-\)最大值\(<v\)的方案数

但是在这里有多个矩形,直接做会有问题,因为非法方案应该是存在一个矩形最大值\(<v\),看\(n\)的范围想到容斥

上公式:\(\displaystyle f(S)=\sum_{T\subset S}(-1)^{|S|-|T|}\cdot g(T)\)

钦定\(T\)为最大值\(<v\)的矩形集合,问题转化为快速求出\(g(T)\)

考虑离散化之后,\((x_i,y_i),(x_i+1,y_i+1)\)一定可以表示最大值限制相同的矩形,枚举离散化后的小矩形统计即可

时间复杂度\(O(n^3\cdot2^n)\)

$p.s. $ 这么好的容斥题被我浪费了,我真该死啊——

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/825796.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

专题

求区间第k小值 静态 分块 排序 划分树 动态 主席树 平衡树 子树求交 树上颜色问题 统计颜色数量 对于子树\(x\),子树内同种颜色的点只有深度最浅的对子树外有贡献 #3628. 「2021 集训队互测」树上的孤独 贡献上传:对于\(x\),设它同颜色祖先为\(p\),则\(x\)对路径\(p\thicks…

BEVDet4D: Exploit Temporal Cues in Multi-camera 3D Object Detection阅读小结

BEVDet4D提出:提出BEVDet4D范式,将BEVDet从仅空间的3D扩展到时空4D工作空间。BEVDet4D: Exploit Temporal Cues in Multi-camera 3D Object Detection BEVDet4D:在多相机三维目标检测中利用时间线索 摘要背景:单帧数据包含有限信息,限制了基于视觉的多相机3D目标检测性能。…

H7-TOOL的LUA小程序教程第17期:扩展驱动AD7606, ADS1256,MCP3421, 8路继电器和5路DS18B20(2024-11-01)

LUA脚本的好处是用户可以根据自己注册的一批API(当前TOOL已经提供了几百个函数供大家使用),实现各种小程序,不再限制Flash里面已经下载的程序,就跟手机安装APP差不多,所以在H7-TOOL里面被广泛使用,支持在线调试运行,支持离线运行。TOOL的LUA教程争取做到大家可以无痛调…

Print和Println区别

看这样一段程序: // 我的减重程序,lbs是磅的简称package mainimport ("fmt" )func main() {fmt.Println("My weight on the surface of Mars is ")fmt.Println(112 * 0.3783)fmt.Println(" lbs, and I would be ")fmt.Println(19 * 365 / 687)…

【semantic Kernel】Semantic Kernel Tools(VS Code插件)

2023年4月13日,Microsoft发布了一个 Semantic Kernel 的 VS Code 插件,Semantic Kernel Tools,用于进行Semantic Function的开发和调试工作。 Semantic Kernel Tools的安装只需要VS Code即可,不需要额外的其他的环境。 在 VS Code的扩展中搜索 Semantic Kernel Tools ,点击…

java.file文件与IO流.study

但断电后后数据消失。 而IO流就是对数据进行读写 File创建对象: 绝对路径与相对路径: File提供的判断文件类型,获取文件信息功能: File创建和删除文件相关方法: File 遍历文件夹的方法: 代码实现: 文件搜索,实现遍历文件夹下的多级目录:遍历删除文件夹及其里边的…

如何高效驾驭海量任务处理的艺术

场景 在支付业务中,我们需要对接很多渠道,再与渠道交易的过程中,因为网络超时,或者渠道返回订单状态结果未知,这是我们一般都需要主动去调用渠道的查询结果去查询订单的最终结果,如果因为某些异常原因积压了大批量这样的订单,我们怎么如何高速快速的查询这种订单? MySQ…

学期(2024-2025-1) 学号(20241420) 《计算机基础与程序设计》第六周学习总结

学期(2024-2025-1) 学号(20241420) 《计算机基础与程序设计》第六周学习总结 作业信息这个作业属于哪个课程 <班级链接>(如[https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP))这个作业要求在哪里 <作业要求链接>(https://www.cnblogs.com/rocedu/p/9…

数组篇-代码随想录

数组篇 跳-二分查找-704-力扣 class Solution {public int search(int[] nums, int target) {if (nums == null || nums.length == 0) return -1;if (target < nums[0] || target > nums[nums.length - 1])return -1;int left = 0, right = nums.length - 1;while (left …

闲话 11.2

杂项乱写 11.2也是打上搜了。小木棍 曾经在题库上做过,数据水就过了,交洛谷发现只有 87pts。 《剪 枝 盛 宴》钦定长度:最小肯定是最长的那根木棍,最长肯定是所有木棍的总和,并且这个长度一定只能是总和的因数。 选择顺序:如果选一个长的合法,那么选若干个和相同的短的一…

Nuxt.js 应用中的 nitro:config 事件钩子详解

title: Nuxt.js 应用中的 nitro:config 事件钩子详解 date: 2024/11/2 updated: 2024/11/2 author: cmdragon excerpt: nitro:config 是 Nuxt 3 中的一个生命周期钩子,允许开发者在初始化 Nitro 之前自定义 Nitro 的配置。Nitro 是 Nuxt 3 的服务器引擎,负责处理请求、渲染…