首页 > 其他分享 >vjudge DP

vjudge DP

时间:2023-02-05 21:13:44浏览次数:48  
标签:vjudge sum 转移 枚举 text 复杂度 DP

uoj607 跳蚤电话

正着不好做(还需要考虑非树边),但倒着就变成了每次在树上 删去一个一度点 或 删去一个二度点并合并邻点

树上一般按子树考虑,直接算方案数的话需要合并子树,因此考虑先算概率,这样每个子树就独立了。

设 \(f[i]\) 为随机一个该子树中点的排列为合法删点顺序(不准删 \(fa[i]\))的概率,\(s[i]=\prod_{j\in\text{son}(i)}f[j]\) 。答案为 \((n-1)!s[1]\),转移考虑枚举最后一个被删的点:

  • 为 \(i\):\(s[i]\)
  • 为 \(j\ne i\):分子树 \(j\) 和其他两部分。第一部分显然为 \(s[j]\);令 \(a[1]=i,\cdots,a[k]=j\) 为 \(i\) 到 \(j\) 路径上的点,不难发现 $ a[k],1\le k<j$ 一定是作为二度点被按顺序删掉,这部分概率为 \(\displaystyle\prod_{l=1}^{k-1}\frac{1}{siz[a[l]]-siz[a[l+1]]}\prod_{u\in\text{son}(a[l]),u\ne a[l+1]}f[u]\)(乘的分数为子树 \(a[l]\) 中除子树 \(a[l+1]\) 外的点都要在 \(a[l+1]\) 前被删)

由于转移中钦定了最后被删的点,还要乘上 \(\frac{1}{siz[i]}\)。朴素实现 \(O(n\sum dep^{2})\),直接考虑子树中每个点作为 \(a[l]\) 的贡献可以做到 \(O(n\sum siz)\)

进一步观察,对于 \(a[l],a[l]\in\text{subtree}(j),j\in\text{son}(i)\),\(a[l]\) 对 \(f[i]\) 贡献与对 \(f[j]\) 贡献的区别仅为在 \(a\) 序列开头加了一个 \(i\),可以优化掉。设 \(g[i]=f[i]\cdot siz[i]\),则有 \(\displaystyle g[i]=s[i]+\sum_{j\in\text{son}(i)}g[j]\frac{1}{siz[i]-siz[j]}\prod_{k\in\text{son}(i),k\ne j}f[k]\),时间复杂度 \(O(n)\)

官方题解的算法六把 DP 式子展开能得到非常简单的形式,感觉意义不大就鸽了

uoj181 密码锁

根据竞赛图的性质,SCC 的个数等于缩点后链的前缀数。设这样的前缀为点集 \(S\),等价于求满足 \(S\) 与 \(V-S\) 的连边都是从 \(S\) 连出去的概率之和,暴力枚举 \(S\) \(O(2^{n}m)\)。这步转化非常关键,它让答案的计算方式从图的形态相关弱化为了点集相关

这种题(仅有给定的边权与其他不同)的一个经典套路是只考虑特殊边,统计每个 \(|S|\) 的答案,然后乘上 \(0.5^{|S|(n-|S|)}\)(为了抵消一个 \(0.5\),特殊边的概率应 \(\times2\))。直接想法是对特殊边形成的联通块枚举有贡献的边集,要求这些边构成二分图,那么一定有一部点 \(\subseteq S\),做一个类似背包的 DP 即可(\(f[i]\) 表示 \(|S|=i\) 且 \(S\) 与 \(V-S\) 间的特殊边都是从 \(S\) 连出去的概率之和)。博主并不太懂这种做法,但官方题解说复杂度为 \(O(2^{m}n^{2})\)

考虑一种比较好的实现:对每个联通块枚举 \(\subseteq S\) 的点集,\(O(m)\) 判断一条特殊边是否有贡献,同样做背包,时间复杂度 \(O(2^{m+1}n+n^{2})\)(这样的联通块大小上界为 \(m+1\))

uoj370 滑稽树上滑稽果

题目加粗了“滑稽度”和“大小”,然而还是读错题了,不愧是星际玩家

方便起见,把所有数都为 \(1\) 的二进制位计入答案,然后置为 \(0\),现在所有 \(a\) 的 & 为 \(0\)

根据 sub2 冷静一下,发现答案一定是一条链(从根到叶子滑稽度是不增的),因此我们希望滑稽度尽快到达 \(0\),一个贪心是从小到大拍,根据 sub4 再冷静一下,这个贪心是假的

考虑 DP。设 \(f[s]\) 为链尾的滑稽度,转移枚举下一个数 \(a_i\),则 ckmin(f[s&a[i]], f[s]+(s&a[i]))。看上去 \(a_i\) 可能被重复选择,不过由于 & 性质,选选过的 \(a_i\) 会得到 \(s\&a_{i}=s\),因此不用担心,时间复杂度 \(O(an)\)。

进一步思考,枚举 \(a_i\) 实质上是要得到 s&a[i] 来转移,那么我们可以直接枚举 \(s\) 的子集 \(t\) 转移到 s^t(把 \(s\) 中 \(t\) 包含的位 置为 \(0\)),该转移合法的条件是存在 \(a_i\) 使得 (t&~a[i])==t,容易预处理

复杂度为 \(O(3^{\log_{2}a})\),需要 0.8s,不过加上用贪心结果来剪枝就很快了

uoj312 梦中的题面

吐槽一下官方题解,写得真的烂。看了一晚上没懂算法六

先考虑 \(c=1\),根据 \(b^i\) 不难想到 \(b\) 进制下从低到高 DP。对于 \(b^i\) 这一位,有 \(n-i\) 个数可以任填 \([0,b)\),预处理 \(f[i,j]\) 表示 \(i\) 个取值 \([0,b)\) 的数和为 \(j\) 的方案数。设 \(g[i,j]\) 表示该填 \(b^i\) 位,\(\sum x-n\) 的进位为 \(j\)( \(j\) 取值 \([-1,m)\)),枚举 \(\sum x\) 这一位的和即可转移,复杂度 \(O(m^{3}b)\)

\(c=0\) 需要特殊考虑 \(=b^{i}\) 的数,在上面的 DP 中相当于低位全为 \(0\),直接向 \(b^{i}\) 进一位。考虑加一维 \(k\) 表示剩下的 \(n-i\) 个数中有 \(k\) 个 \(\ne b^{i}\),因此当前位有 \(k\) 个数不为 \(0\)。然后讨论 \(x_i\) 是否等于 \(b^{i}\) 对应转移即可

代码实现上有一些细节,并要注意常数

还有不依赖 \(b\) 的容斥做法,见『模拟赛 3.20 』

CF1342F Make It Ascending

第一道自己想出来的题,虽然比正解多了一个 \(n\)。看这个数据范围就像 \(O(T3^{n}\text{poly }n)\),并且这个 7s 恐怕可以无视 \(\text{poly }n\)

显然操作数最少等价于剩下的数最多,考虑状压 DP 结果序列。设 \(f[i,s,j]\) 为以 \(i\) 结尾的序列,\(s\) 集合中的数或被操作或剩下,末尾数值为 \(j\) 最多能剩下多少数。发现 \(f[i,s]\) 取值范围只有 \(n\),且 \(f[i,s,j]\) 相同时只有最小的 \(j\) 有用,可以反转状态和 DP 值,改设 \(f[i,j,s]\) 为剩下 \(i\) 个数,末尾数在原序列 \(j\) 位置,使用集合 \(s\) 的末尾数最小值。转移就枚举新的末尾数位置 \(k\) 和加给 \(k\) 的集合 \(t\subseteq U-s\),输出方案就记录转移。时间复杂度 \(O(T3^{n}n^{3})\) 不满

其实也容易优化掉一个 \(n\),发现转移时若 \(i,j,s,t\) 一定时只有最小的 \(k\) 有用。另外这题有很多做法

CF1239E Turtle

根据题解理解不难,但如何想到?

直接做很难,先找一些性质:

  1. 第一行第一个数、第二行最后一个数是最小的两个数,因为所有路径都经过这两点。结合第二条反证也可
  2. 第一行的数单增,第二行单减:路径和为 第一行前缀 \(+\) 第二行后缀 的形式,调换第一行的逆序对 \(i,j\),对于 \(\ge j\) 的前缀无影响,但 \(<j\) 的前缀变小了。第二行类似
  3. 考虑拐点从 \(i\) 变到 \(i+1\) 的增量 \(a_{1,i+1}-a_{2,i}\),根据第二条不难发现单增,因此取到最大值的路径拐点为 \(1,n\)(增量初值可能 \(<0\)),即答案为 \(\max(a_{1,1}+\sum a_{2},\sum a_{1}+a_{2,n})\)

最后问题转化为把较大的 \(2n-2\) 个数分成两部分(每部分 \(n-1\) 个数),使较大的和最小。bitset 背包即可做到时空 \(O(\frac{n^{3}a}{\omega})\)(为了输出方案不能滚动)

CF613E Puzzle Lover

模拟赛做过,但仍调了很久,没救了。做法略

需要判断 \(s,t\) 两子串是否同构,当时的做法是哈希。但实际上可以转化为求两后缀 LCP,瓶颈在于 DP 因此直接 \(O(|s||w|)\) 递推即可,代码阳间许多

DP 部分,计数的不重不漏其实是很严谨的。把路径分成三部分:第一部分先向左再拐回来,第二部分单调向右,第三部分先向右再拐回来。第一部分枚举向左的开始位置和长度(\(\ge1\),特判掉单个位置与 \(w_1\) 匹配)作为 DP 初值,第二部分 DP,从上一列转移,第三部分枚举向右的开始位置和长度(\(=0\text{ or }>1\),\(=1\) 的情况包含在第二部分中)统计答案

考虑哪些串被漏掉:第二部分向左,或仅有第三部分。reverse \(s\) 再做一遍即可(注意不能 reverse \(w\))

CF582D Number of Binominal Coefficients

以前口胡过,今天一写果然很恶心

库莫尔定理转化为求 \(0\le x,y\le A,x+y\le A\) 且 \(x+y\) 进位次数 \(\ge\alpha\) 的解的个数,数位 DP 即可。口胡五分钟,调试两小时

以 \(p\le x+y<p+a\) 为例推一下式子:

\[\sum_{i=p}^{p+a-1}\sum_{x=0}^{p-1}\sum_{y=0}^{p-1}[x+y=i] \\ =\sum_{i=p}^{p+a-1}\sum_{x=0}^{p-1}[0\le i-x\le p-1] \\ =\sum_{i=p}^{p+a-1}\min(p-1,i)-\max(0,i-p+1)+1 \\ =\sum_{i=p}^{p+a-1}(p-1)-(i-p+1)+1 \\ =\frac{a(2p-a-1)}{2} \]

AGC34E Complete Compress

因为细节 WA 了一次,还是看了题解

AGC20E Encoding Subsets

先考虑 \(1\) 不能变成 \(0\):区间 DP。设 \(f[l,r]\) 为区间 \([l,r]\) 的答案,转移枚举能折叠成一个字符的后缀长度,\(g[l,r]\) 为 \([l,r]\) 折叠成一个字符的方案数,转移枚举 \(|A|\)。原题先将记区间改为记串,转移 \(g[s]\) 时要乘上 \(f[\text{ 截取出的 }\frac{|s|}{|A|}\text{ 段的按位与 }]\)。这样会产生不是原串子串的串,记搜即可

关键在于计算复杂度,官方题解给了三种方法:

  • 程序员:打表发现需要计算的串只有 \(49893\) ,转移需要 \(O(n^{2})\),二者都不满
  • 数学:长度 \(\le12\) 的串只有 \(2^{13}\) 种,而 \(12\times8>100\),因此要产生 \(>12\) 的串只能折叠两次(每次折叠长度至少减半),折叠出的子串可以表示成 \(s[i:i+k-1],s[i+k,i+2k-1],s[j:j+k-1],s[j+k,j+2k-1]\) 的按位与,只有 \(O(n^{3})\) 种,再加上 \(n^{2}\) 转移,总复杂度为 \(O(2^{\frac{n}{8}}n^{2}+n^{5})\) 不满
  • 信仰:写出来跑一下发现 \(O(\text{能过})\)

这题带来一个启示就是数据范围小时一些奇怪复杂度的东西可能能过,不要直接放弃

AGC36D Negative Cycle

没有负环等价于差分约束有解,设最终取值为 \(x_i,d_{i}=x_{i}-x_{i+1}\),那么 \(x_{i}\ge x_{i+1}\Rightarrow d_{i}\ge0\),存在边 \((i,j,-1)\) 等价于 \(x_{i}-1\ge x_{j}\Rightarrow\sum_{k=i}^{j-1}d_{k}\ge1\),为了使答案最小,边能保留就保留,因此当且仅当 \(\sum_{k=i}^{j-1}d_{k}=0\) 时才会删除边 \((i,j,-1)\)。边权为 \(1\) 的边同理

进一步思考发现 \(q_{i}\le1\),因为把 \(>1\) 的变为 \(1\) 不会影响边权为 \(-1\) 的边,但会少删一些边权为 \(1\) 的边。然后就可以 DP 了,设 \(f[i,j]\) 为 \(q\) 最后两个 \(=1\) 的位置为 \(i,j\),枚举上一个 \(=1\) 的位置 \(k\),二维前缀和一下就能 \(O(1)\) 转移,时间复杂度 \(O(n^{3})\)

AGC28D Chords

一个重要转化是圆上连线相交等价于序列上相交但不包含,这样就可以用区间 \([l,r]\) 表示一个连通块(不存在从区间内连出去的边,\(l,r\) 连通但不一定与区间内所有点连通)。设 \(c(l,r)\) 表示 \([l,r]\) 有多少点没有连边,\(g(n)\) 表示 \(n\) 个点随便连边的方案数,显然 \(n\) 为偶数时\(=\prod_{2i+1\le n}(2i+1)\),否则 \(=0\)。

考虑分每个连通块算。设 \(f[i,j]\) 为存在连通块 \([i,j]\) 时区间 \([i,j]\) 的连边方案数,答案为 \(\sum_{i\le j}f[i,j]\times g(i-1+n-j)\)。计算 \(f\) 可以容斥:\(\displaystyle f[i,j]=g(c(i,j))-\sum_{k=i+1}^{j-1}f[i,k]\times g(c(k+1,j))\)

标签:vjudge,sum,转移,枚举,text,复杂度,DP
From: https://www.cnblogs.com/401rk8/p/16525276.html

相关文章

  • Codeforces Round #848 (Div. 2)D. Flexible String Revisit-dp、初等数学
    题目:https://codeforces.com/problemset/problem/1778/D场内打的,首先很容易想到答案来自于a、b不同的位置有几个,设\(f_k\)表示当前有k个不同的位置要复原到完全一样需要多......
  • Codeforces Round #840 (Div. 2) E. Node Pairs-图论、小dp
    题目链接:https://codeforces.com/problemset/problem/1763/E题意有点绕,大概就是给一个p,现在希望找到一个n个点的有向图G,恰好有p个点对\(1\lequ<v\leqn\)使得\(u\tov\)......
  • 阿里云轻量应用服务器快速安装WordPress网站系统
    阿里云轻量应用服务器相比ECS服务器的最大特点在于可以较快的部署WEB服务器,比如我们在前面有介绍到安装宝塔面板。我们在轻量服务器后台还可以看到可以安装WordPress和LAMP......
  • 2023牛客寒假算法基础集训营6 (B 思维+二分)(D 字符串匹配dp)(E 生成树+思维)(I 思维+
    2023牛客寒假算法基础集训营6(B思维+二分)(D字符串匹配dp)(E生成树+思维)(I思维+bfs)B阿宁的倍数题目大意:给定一个长度为n的数组a,有q次操作。修改:数组末尾增加......
  • 【AT_dp_r】Walk
    又是简单题。我们知道弗洛伊德可以求解传递闭包。我们有矩阵\(M\),我们给\(M_{k,i,j}\)定义为\(i\toj\)长度为\(k\)的路径数,细想不难发现有转移:\(M_{k,i,j}=\su......
  • 闫氏DP法
    闫氏dp法与传统dp的区别是————从集合角度考虑dp问题dp问题一、状态表示(f[i][j])(1)集合明确f[i][j]表示的是什么集合如:数字三角形模型中f[i][j]表示的是从(1,1)到(i,j......
  • 动态规划DP
    动态规划DP一般DP的组成一般DP主要分为两个部分:表示状态,状态转移这里以P1216[USACO1.5][IOI1994]数字三角形NumberTriangles为例表示状态答案为从上到下的路径......
  • P1472 奶牛家谱 Cow Pedigrees(DP)
    题目描述农民约翰准备购买一群新奶牛。在这个新的奶牛群中,每一个母亲奶牛都生两个小奶牛。这些奶牛间的关系可以用二叉树来表示。这些二叉树总共有N个节点(3<=N<200)......
  • 缩点-将图转化为 DAG 跑 DP :P1455,P2169
    之前有提到,缩点可以将一张有向图转化为一张有向无环图(DAG),这样我们就可以在图上跑DP了。而我们实现DP的手段一般是在拓扑排序中实现,有时候也会用到最短路。P1455https......
  • Error: client: etcd cluster is unavailable or misconfigured; error #0: client:
    这种报错是因为配置出现了问题我们需要修改etcd的配置文件就可以了vim/etc/etcd/etcd.conf  重启etcd即可systemctlrestartetcd.service ......