5.23晚
NO.1 来源: BZOJ 4197 [NOI2015] 寿司晚宴
分类: 状压 dp
简要题解:
- 注意到n≤500,至有一个大于20 的质因数,而小于20的质数只有8个,我们可以令f[S][T] 表示第一个人选的小于20的质数集合为S,第一个人选的小于20的质数集合为T的方案数。
- 把2到500的数按照大于20的质因数(没有就是1)排序,依次讨论大质因数。此时:
- 令g[0/1][S][T],第一维表示这个大质因数分给第1或者第2个人。
- 假如一个数x 包含的小于20的质数集合为
Q ,那么:
g[0][S][T]→g[0][S∪Q][T] (T∩Q=∅)g[1][S][T]→g[1][S][T∪Q] (S∩Q=∅) - f[S][T]=g[0][S][T]+g[1][S][T]−f[S][T] (两个人都没选这个大质因数的情况算了两遍)
反思
- 显然这题和一个数的质因数集合有关,但小于500质因数过多,所以要分类讨论。
- 其实DP本质上是基于一种递推的拓扑序的,所以这种排序要想得到。
5.25晚
NO.2 来源: BZOJ 3162 独钓寒江雪
分类: 树形 dp ,Hash
简要题解:
-状态还是继承了最大独立的方法。f(x,0/1) 表示以x为根的子树,选与不选x 的独立集方案数。
- 首先转为有根树。因为两个形态形同的树有一样的大小,所以选择重心作为根不会破坏相同的结构。
- 一棵子树的形态用一个可以递推的Hash值来表示。
- 把
- 可能会有两个重心,最后需要讨论一下答案。
反思
- 树的形态可以Hash
- 暴力求C的方法:
LL C(LL n,LL m){
LL ret=1;
for(;m;m--)
ret= ret*(n-m+1)%M*inv[m]%M;
return ret;
}
5.25晚
NO.3 来源: BZOJ 1040 [ZJOI2008]骑士
分类: 树形 dp ,环套树
简要题解:
- 对于每棵树,找到环上的一条边e,设边上的两端点分别为
S 和Tf(x,0/1) 表示以x为根的子树,选与不选x 的权值最大值。 - 考虑断掉
e ,dp,有以下两种情况:
- 不取S,
T 任意,我们以u为根跑一遍树形DP,取f(S,0) - 不取T,
S 任意,我们以v为根跑一遍树形DP,取f(T,0)
4.答案是两个值中的最大值
- 不取S,
反思
- 其实就是仙人掌的弱化版:找环+dp。
5.26下午
NO.4 BZOJ 4167 永远的竹笋采摘
分类: 分块 暴力
简要题解:
- 很容易写出O(n2k) 的暴力,令f(i,j) 表示前i 个数,分出
j 块的最小花费,那么f(i,j)=min1<=k<j{f(k−1,j−1)+|A[i]−A[k]|}
其中A[i]与A[k]是这个区间中差值最小的,这样的转移记为(i,k)。 - 由于是随机数据,其实可以有效转移的点对很少。可以用一下分块的思想求出:
- 预处理dmin(b,x) 表示b 这个块中与
x 差的最小值。 - 倒序枚举每一个i,检查当前块是否存在满足条件的
(i,k) 。 - 检查i后面的块
b ,如果dmin(b,A[i]) 不大于当前最小值 ,那么
检查当前块是否存在满足条件的(i,k),并且还要满足不存在j>i 使得|A[j]−A[k]|<|A[i]−A[k]|,这一点可以用树状数组维护一个最小值。
- 预处理dmin(b,x) 表示b 这个块中与
反思
- 这种乱搞的题我没话说了。
5.26晚
NO.5 BZOJ 4513: [Sdoi2016]储能表
分类: 数位dp
简要题解:
- g(t,a,b,c) (a,b,c∈{0,1}) 表示从低到高第x位的方案数。
a=0 表示i的前t 位比n的前x 位小,a=1表示不作要求;- b=0表示j的前
t 位比m的前x 位小,b=1表示不作要求; - c=0表示i xor j的前t位大于等于
k 的前x,c=1 表示不作要求;
- f(t,a,b,c) 表示对应的和。
- 根据限制转移: 枚举0≤p≤max(a,n[i]), 0≤q≤max(b,m[i]), 令j=a or (p<n[i]),k=b|(q<m[i]) l=c or ((q xor p)>k[i])
那么f(t,a,b,c)←g(i−1,j,k,l)∗((p xor q)−c[i])∗2i−1f(t,a,b,c)←f(i−1,j,k,l)g(i,a,b,c)←g(i−1,j,k,l)
反思
- 这类数位dp的思路就是限制什么,枚举什么,以及限制条件的相互转化。
- 注意到位运算的问题都可以每一个二进制位分开考虑