您的位置:首页 > 其它

12.8 省选训练总结3(1) DP

2017-12-08 11:55 211 查看

目录

树形DP

完成情况题目出处
ACChoosing Capital for TreelandCodeforces 219 D #135
A simple graph problemHDU 4980

数位DP

完成情况题目出处
Round NumbersPOJ 3252
F(x)HDU 4734
Beautiful numbersCodeforces 55 D #51
阿里云秘钥池计蒜之道2017复赛

状压DP

完成情况题目出处
ACLittle Pony and Harmony ChestCodeforces 453 B #259
A Graph ProblemCDOJ 1296

概率DP

完成情况题目出处
ACAeroplane chessHDU 4405
ACBag of miceCodeforces 148 D #105
HighlanderSGU 385

树形DP

无非两种:

父亲到儿子,儿子到父亲,合并子树等。

转根

Choosing Capital for Treeland

给出N个点,其中有N−1条有向边,边的方向可以改变,问最少改变多少条边可以从某一个点到达任意一个点,同时求出这些点。

我的做法是先自底向上一次DP求出该点到子树要转几条边,然后自上至底再做一次求到非子树。

也可以求出一个之后用换根做。

关于重心和中心

重心是一个DP,点分治要用。

求中心可以先找直径,直径可以用两次DFS做。

A simple graph problem


4000
一颗n个节点的树,每条边有边权。现在你要在这些节点让放一些队员,让队员访问完全部的边。放置一个队员的代价是K,一个队员经过一条边需要付出边权的代价。并且一个队员不能经过同一条边两次。问最小代价是多少。

其实队员路线可以有重复(只要边权足够小,K却很大)。

可以用dp[i][j]表示i这个节点的子树的边全部访问完全,并且有j条向上的队员。(队员总是可以向上走)

合并子树时要考虑相互之间可能造成的影响。

数位DP

有三种写法:

第一种:从高位到低位,记一个flag看看有没有顶住上界。

第二种:预处理出定长度的dp值,然后对每一个上界下的不同位求一个答案然后合并。(例如1∼233,分别求出0∗∗∼1∗∗,20∗∼22∗,230∼233的答案)

第三种,类似于第一种,但不记上界,只是往下一位走时单独算一个“从此位开始不同的方案数”加进去。

Round Numbers

算出区间内二进制中0的个数大于等于1的个数的数字有多少个。

dp[i][j][flag]表示前i位j个0的方案数。

F(x)

我们定义十进制数x的权值为

f(x)=a[n]∗2n−1+a[n−1]∗2n−2+…a[2]∗2+a[1]∗1

a(i)表示十进制数x中第i位的数字。

题目给出a,b,求出0∼b有多少个i使f(i)不大于a。

一眼看去就非常适合记忆化搜索。也可以第二种数位DP代替,dp[i][res]表示考虑i位,f值为res的方案数。

Beautiful numbers

求区间内能整除所有组成它的非0数字的数的个数。

可以考虑记忆化搜索,因为要看整除,记录对1∼9取模的值就行。然后它们的公倍数是2520,所以只需要记模2520的结果。

初步可以写出dfs(len,mod,T,flag),T为想一种方法来表示1∼9哪些出现过。

直接记lcm?2520记不下。

状压可以吗?28=256,还是大。

但是可以发现这个lcm值肯定是2[0,1,2,3]×3[0,1,2]×5[0,1]×7[0,1],一共只有48个取值,用map映射一下就可以了。

阿里云秘钥池

求1到n之间,在p进制下,每位两两互素的数的个数。

假设在上一位,每个j(j∈[1,p−1])有一个方案数f0[j],那么,这一次更新的时候相当于对于i要求一个新的方案

f1[i]=∑j=1p−1[gcd(i,j)==1]×f0[j]

暴力转移的复杂度是O(n2logn)

考虑优化:

∑j=1p−1[gcd(i,j)==1]×f0[j]

=∑j=1p−1∑d|i,d|jμ(d)f0[j]

=∑d|iμ(d)∑j=1⌊p−1d⌋f0[d×j]

可以发现,∑f0[d×j]是可以在O(nlogn)时间内预处理出来的,然后对于求和式∑d|iμ(d)是近似O(logn)复杂度的,所以说复杂度降到了O(nlogn)。

状压DP

精髓在于把一个复杂的状态用一个进制数来表示

Little Pony and Harmony Chest

给出一个序列a,求一个序列b,b序列的数两两互质,问能够使得∑|ai−bi|最小的方案。

ai≤30,{a}≤100。

既然有ai≤30,那我bi取任何大于60的数的时候,还不如取1呢。所以只需要找出小于60的那十几个质数做状态压缩。

dp[i][T]表示考虑前i个数,现在的质数使用状态的是T的代价。



A Graph Problem

有n个城市和m条双向路,有k个人,每个人选了两个不同的城市。现在让你尽可能多的删除边,使得这k个人每个人都可以从选的两个之间移动。

这题太神了让我自己来理一理。

dp0[T]:

表示状态T里的点连在一起,刚好组成一个连通块的时候,最少需要多少边。

这个结果要么是“不可行”,要么是count−1

dp1[T]:

表示状态T里的点连在一起,在一个连通块内的时候,最少需要多少边。

注意,这种不同于上一种,可以有其他的点也并入

要转移到这一种的时候,就枚举包含dp0的集,更新。

接下来,对这些要求做并查集。这k个城市对,可以分成一些联通块。

dp2[S]:

表示这些连通块对应的点全部连在一起的时候,最少需要多少边。

注意,这里重新设置了状态,状态里的0/1不再是点选不选,是连通块选不选。

这里可以直接转化一下状态,从dp1转过来。

dp3[S]:

表示这些集合可以相互不连通的时候,最少需要多少边。

这个地方的转移就是把这个S分成几部分,把它们的dp2加起来。

总结一下:

dp0[T]=connected?count−1:−1。

dp1[T1]=dp0[T](T1⊆T)

dp2[S]=dp1[T](S→T)(→指从集合的状态变换为点的状态)

dp3[S]=∑m1dp2[Si](S1∪S2∪…∪Sm=S)

概率与期望DP

如果是在一个DAG上可以拓扑序列方程。

如果是繁杂的环可以高斯消元。

如果环的焦点很少(很多个环的产生是因为同一个点),可以带参数做DP。

Aeroplane chess

在一条有n个格点的线上掷骰子,有1∼6六个值,如果当前为止超过n,则胜利,有m个跳跃点,到x位置可以直接飞到y位置(x<y),问从起点开始到终点掷骰子的期望数。

dp[i]表示从i走到终点的期望步数。

方程是这样的:

dp[i]=0(i>n)

dp[i]=∑dp[i+[1∼6]]/6+1 (不是跳跃点)

dp[x]=dp[y]

Bag of mice

袋子里有w个白和b个黑 ,A和B轮流从袋子里抓。谁先抓到白色谁就赢。A每次随机抓一个,B每次随机抓完一个之后会有另一个随机颜色掉出来。如果两个人都没有抓到白色则B赢。A先抓,问A赢的概率。

设dp[i][j]表示剩i白j黑,该A抓的获胜概率。

转移分情况:

A白

ii+j×1

A黑B黑掉出黑

ji+j×j−1i+j−1×j−2i+j−2×dp[i][j−3]

A黑B黑掉出白

ji+j×j−1i+j−1×ii+j−2×dp[i−1][j−2]

A黑B白

0

Highlander

随机一个错位排列 {i1,i2,…in},对应了一张有向图的边 E={(1,i1),(2,i2),…,(n,in)}。问在最长环上的顶点数的期望值。 2≤n≤100

用 f[i][j][k]表示了错位排列中i个数字已经确定,最长环为j,且有k个的方案数。

转移:

f[i][i][1]=Aini

意义:本身是一个最长环,除去环的环绕性质

f[i][j][1]=∑l=2min(j,i−j+1)∑k=1i−jlf[i−j][l][k]×Ajn−i+jj

意义:构造一个新的最长环,然后剩余的部分只要小于新的最长环长度就行。

f[i][j][k]=f[i−j][j][k−1]×Ajn−i+jjk

意义:已经有了一个等长的最长环,再增加一个。注意,先后增加顺序不同是等价的,所以除以k。

答案是:

∑nj=2∑nk=1jk⋅f[n][j][k]∑nj=2∑nk=1f[n][j][k]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: