zoukankan      html  css  js  c++  java
  • 整体dp小结

    本来这一块是做在“Ideas and Tricks”里面的,但是鉴于最近刚学dp优化minmax容斥,而且随便开了一道又开出一个神仙整体dp题,所以把它单独拿出来总结一下。

    一般的多个限制求总方案数问题

    首先要转化题意,一般对于“全部满足”一些限制的时候,可以转化成所有乱选,然后限定一些一定不成立(前提是不成立的比较好算),进行容斥

    然后一般这种题我们会发现容斥出来的答案(或者知道这个就能算出答案)的东西是很好设计成状态且易于转移的,所以就可以转而用dp来表示这种状态的方案数带上容斥系数。

    例如NOI2020D1T2,在考虑树上进行容斥以后,对于一些点不成立,限制无非就是儿子到父亲的一段区间必须染白,所以就可以用$dp[i][j]$表示到第$i$个点,限制最上面到$j$的方案数。

    然后树上的转移一般又会带有一些优化,比如说一些求和的问题,在儿子合并时可以通过线段树合并来优化时空复杂度。

    再区别一下这道题(不是整体dp),这个选最大独立集对儿子合并也是有条件的(不能线段树合并),但是是区间max,不需要怎么更新父亲信息,直接长链剖分,再轻儿子深度处更新答案即可

    对于这道题,直接把树边搞成限制,然后如果一些限制强制不成立那么一定会把这棵树连成若干条链,任意一个结点入度出度都不能大于等于2。然后直接把有几条链设进状态里,dp就很容易了。

    minmax容斥的dp优化

     有:$$max(S)=sum_{varnothing ot=Ssubseteq T}(-1)^{|T|-1}min(T)$$

    $$kthmax(S)=sum_{varnothing ot=Tsubseteq S}(-1)^{|T|-k}inom{|T|-1}{k-1}min(T)$$

    这种dp一般有一个特点:就是枚举子集以后的$min(T)$特别好算而且答案很小

    考虑每次枚举子集的时候直接把这个原本的答案设进状态然后表示集合个数乘上正负系数和组合系数

    经典例题如重返现世,我们会发现对于一个子集的$min(T)$,我们只要知道这个子集里的$sum P[i]$即可,而又有$m leq 10000$,所以就可以把概率总和设进状态,然后表示集合个数乘上容斥系数。

    考虑带有组合数的递推式,我们无法直接通过简单的加减来实现这个转移,而直接把集合大小记下来状态又存不下——观察数据范围发现$k$非常的小。

    组合数是怎么推的?——$C(n,m)=C(n-1,m-1)+C(n-1,m)$这个$k$表示的就是列数,元素个数一直都是$n-1$,即选上这个元素以后所产生的贡献可以由$k$和$k-1$之和来表示(带$k$仅仅是为了组合数转移)。

    所以就有:(选的时候)

    $$dp[i][k][S]=dp[i-1][k-1][S-P[i]]-dp[i-1][k][S-P[i]]$$

    其中正号负号取决于容斥元素个数奇偶性。

    这里有一个很好的初始化技巧——可以把$dp[0][0][0]$设成$0$,剩下的$dp[0][k][0]$设成$-1$,这样在刚好从$T-1$个元素转成$T$个元素时,这个集合对于选择$T$个开始有1的贡献

    还有一道与之类似的题:给你一个长度为$n$的序列,初始全为白色,每次你等概率一段区间$[l,r]$把它染黑,问至少有$k$个元素被染黑的期望步数,$n leq 100$

    考虑一样的minmax容斥,现在要求$min(T)$,这个也挺好处理,对于所有$n*(n+1)/2$个区间,把所有未选的点所构成的一段段区间,期望就是

    $$frac{frac{n*(n+1)}{2}}{frac{n*(n+1)}{2}-sum frac{l*(l+1)}{2}}$$

    所以我们$dp[k][j][i]$表示在$k$的情况下$sum l*(l+1)/2 $的和为$j$,最后一个选的是$i$。与上面类似递推即可。复杂度为$n^{5}$,因为只会有$10000$个答案,打表就能过。

    (听说有$n^{5}$较大剪枝的另一种推法?留坑补补

    顺便再讲一个minmax常用优化——FWT

    例题:PKUWC2018随机游走HAOI2015按位或

    前者是FWT最后统计方案时是子集卷积,这很容易想到FWT的or操作,对于一些子集的值乘上正负系数直接卷起来就可以处理多次询问了。

    后者则是通过转化题意,把“至少选到一个”的概率转化成“一个都不选”的概率,然后这一位的补集的卷积就是总概率,FWT可以快速处理。

    Bonus-LOJ575

    其实我觉得这个25~40的部分分也挺神的,先讲一讲。

    考虑状压dp可以设$dp[S][i]$表示哪些已经选了,最后一位是$i$。但是我们发现没有必要保存前面填了哪些数这个信息,只要知道相对大小即可把很多状态绑起来转移,而对于要填的下一个数只要记录前一个数的状态即可。

    所以设$dp[i][j]$表示填到第$i$个数,最后一个数在已填的数里面时第$j$大的,然后$n^{3}$转移,可以优化到$n^{2}$,但是再没有什么优化空间。

    正解是类似于整体dp的思路,我们先假设把所有小于号提取出来,剩下的大于号随意,那么方案数就是$n!prod frac{1}{l!}$,$l$是每一个小于号段的长度。

    所以可以进行容斥——使得一些随便选的大于号强制选小于号使连成一段。设$dp[i]$表示到第$i$位的答案,那么就有方程式:

    $$dp[i]=sum_{j<i} dp[j] (-1)^{num(j+1,i-1)} frac{i^{underline{i-j}}}{(i-j)!} [s[i]=='>']$$

    $num(l,r)$表示$l$到$r$有几个大于号被强制选为小于号,然后这个式子显然可以分治FFT优化,复杂度为$O(nlog(n))$

    后记

    感觉以小结的形式把一些类似的题目总和在一起的方式还是不错的,虽然有点废时间。再有时间可能会更新一些有关概率期望的内容。

  • 相关阅读:
    【墨天轮专访第四期】华为云GaussDB苏光牛:发挥生态优势,培养应用型DBA
    go语言中iota和左移<< 右移<<
    gin Http请求Body和Header的获取 request post form Query header
    C# 【::】符号用法
    HyperV 无法Ping通主机原因
    远程协助
    单独安装mysql客户端
    MySQL中间件之ProxySQL(3):初试读写分离
    ProxySQL:简介和安装(1)
    dbdeployer MySQL沙盒部署详解
  • 原文地址:https://www.cnblogs.com/Forever-666/p/13966650.html
Copyright © 2011-2022 走看看