前言:最近刷了一些水题…
CH5E26
题意:一副不含王的扑克牌由52张牌组成,由红桃、黑桃、梅花、方块4组牌组成,每组13张不同的面值。现在给定 52 张牌中的若干张,请计算将它们排成一列,相邻的牌面值不同的方案数
计数 d p dp dp
考虑到剩 1 张花色,剩 2 张花色 … 本质是一样的
令 f a , b , c , d f_{a,b,c,d} fa,b,c,d 表示还剩 a a a 种剩一个花色的, b b b 种剩两个花色的
如果选一个只剩一种花色的
f a , b , c , d = a ∗ f a − 1 , b , c , d f_{a,b,c,d}=a*f_{a-1,b,c,d} fa,b,c,d=a∗fa−1,b,c,d
选剩两种花色的
f a , b , c , d = 2 ∗ b ∗ f a + 1 , b − 1 , c , d f_{a,b,c,d}=2*b*f_{a+1,b-1,c,d} fa,b,c,d=2∗b∗fa+1,b−1,c,d
等等,好像会算重
考虑上一次选的什么,发现与这一层有关的,只与上一层剩几个花色有关
如果上一层选的剩 3 种花色的,那么这一层就有一种 2 种花色的不能选
于是记录 l a s las las
f a , b , c , d = ( a − [ l a s = 2 ] ) ∗ f a − 1 , b , c , d f_{a,b,c,d}=(a-[las=2])*f_{a-1,b,c,d} fa,b,c,d=(a−[las=2])∗fa−1,b,c,d
f a , b , c , d = 2 ∗ ( b − [ l a s = 3 ] ) ∗ f a + 1 , b − 1 , c , d f_{a,b,c,d}=2*(b-[las=3])*f_{a+1,b-1,c,d} fa,b,c,d=2∗(b−[las=3])∗fa+1,b−1,c,d
f a , b , c , d = 3 ∗ ( c − [ l a s = 4 ] ) ∗ f a , b + 1 , c − 1 , d f_{a,b,c,d}=3*(c-[las=4])*f_{a,b+1,c-1,d} fa,b,c,d=3∗(c−[las=4])∗fa,b+1,c−1,d
f a , b , c , d = 4 ∗ d ∗ f a , b , c + 1 , d − 1 f_{a,b,c,d}=4*d*f_{a,b,c+1,d-1} fa,b,c,d=4∗d∗fa,b,c+1,d−1
HDU 2196
给一棵树,求从每一个点出发的最长距离 n ≤ 1 e 5 n\le 1e5 n≤1e5
先做一遍树形 d p dp dp,求出每个点向下的最长路径
考虑从祖先转移过来的,为 m a x max max ( 祖先向下的最长路,祖先继续向上的最长路)
等等,好像出锅了,如果祖先向下的最长就是自己呢
于是还要处理出次长链,两次 dp 就可以了
IOI 2000 邮局
题意:选出 m m m 个邮局, n n n 个村庄,每个村庄会走到离它最近的邮局,问总代价的最小值
暴力转移:
f i , j = f k , j − 1 + c o s t ( k + 1 , i ) f_{i,j}=f_{k,j-1}+cost(k+1,i) fi,j=fk,j−1+cost(k+1,i)
首先有一个不是正解的东西:
考虑到选的邮局越多就一定越优,于是可以让每选一个邮局就加上一个 m i d mid mid,然后二分 m i d mid mid 直到选出来的个数正好是 m m m,俗称 d p dp dp 凸优化
正解:四边形不等式
感性理解:令 f i , j f_{i,j} fi,j 的决策点为 p i , j p_{i,j} pi,j,则 p i , j − 1 ≤ p i , j ≤ p i + 1 , j p_{i,j-1}\le p_{i,j}\le p_{i+1,j} pi,j−1≤pi,j≤pi+1,j
因为如果少了一个邮局,就更加分散,决策点更靠前
所有当前的决策点在 [ p i , j − 1 , p i + 1 , j ] [p_{i,j-1},p_{i+1,j}] [pi,j−1,pi+1,j],对复杂度的贡献就是 p i + 1 , j − p i , j − 1 p_{i+1,j}-p_{i,j-1} pi+1,j−pi,j−1,求个和可以证明是 O ( n m ) O(nm) O(nm)
POJ 1191
拆方差
∑ i = 1 n ( x i − x ‾ ) 2 = n ∗ x ‾ 2 + ∑ i = 1 n x i 2 − 2 ∗ n ∗ x ‾ 2 \sum_{i=1}^n(x_i-\overline x)^2=n*\overline x^2+\sum_{i=1}^n x_i^2-2*n*\overline x^2 ∑i=1n(xi−x)2=n∗x2+∑i=1nxi2−2∗n∗x2
需要最小化 ∑ i = 1 n x i 2 \sum_{i=1}^n x_i^2 ∑i=1nxi2
f x 1 , y 1 , x 2 , y 2 , k f_{x1,y1,x2,y2,k} fx1,y1,x2,y2,k 表示当前矩阵,还可以分割 k k k 次的最小代价
枚举横切还是竖切,记忆化搜索
POJ 1390
题意:给你一个颜色块序列,每次你可以删除一些相同颜色并且相邻的颜色块,并获得删除数目平方的收益,现在给你一个颜色块序列,问收益最大是多少?
挺好的题,比较容易想到区间 d p dp dp, f l , r f_{l,r} fl,r 表示区间 [ l , r ] [l,r] [l,r] 的最优方案
发现没法转移,考虑加维度
f l , r , k f_{l,r,k} fl,r,k 表示 [ l , r ] [l,r] [l,r], r r r 后有 k 个更它颜色相同的块的最优方案
枚举当前是见好就收还是放手一搏
f l , r , k = m a x ( f l , r − 1 , 0 + k 2 , f l , p , c n t p + k + f p + 1 , r − 1 , 0 ) ( c o l p = c o l i ) f_{l,r,k}=max(f_{l,r-1,0}+k^2,f_{l,p,cnt_p+k}+f_{p+1,r-1,0})(col_p=col_i) fl,r,k=max(fl,r−1,0+k2,fl,p,cntp+k+fp+1,r−1,0)(colp=coli)
POJ 2288
题意:给出 n 个点,m 条边。每个点有一个权值 w。找出一条汉密尔顿路径,使它的值最大
一条汉密尔顿路径的值由三部分组成:
路径上每个点的权值之和
路径上每条边u-v,将其权值的积累加起来。即 w [ u ] ∗ w [ v ] w[u]*w[v] w[u]∗w[v]
如果三个点形成一个三角形,例如 i,i+1,i+2,那么将 w [ i ] ∗ w [ i + 1 ] ∗ w [ i + 2 ] w[i]*w[i+1]*w[i+2] w[i]∗w[i+1]∗w[i+2]累加起
考虑如何加入三角形的贡献,需要加两维, f S , i , j f_{S,i,j} fS,i,j 表示当前状态,上一个是 i i i,上上个是 j j j 的最大贡献
枚举下一个转移即可
POJ 2374
自己写的时候从上往下 dp,细节有点多,其实可以倒过来,从下往上走
d p i , 0 / 1 dp_{i,0/1} dpi,0/1 表示走到第 i 层,在左 / 右端点的最小长度
显然只能由它的端点往下走碰到的第一块来转移
于是走过一块就在线段树上更新,权值为它的层数,转移的时候线段树上查一个 m a x max max 即可
POJ 3252
数位 d p dp dp, f i , j , k f_{i,j,k} fi,j,k 表示到了第 i 位,有 j 个 0,k 个 1 的个数
前导 0 不能算到 0 的贡献里,记忆化搜索就过了
POJ 3709
首先如果要缩一段的话,一定缩成开头
f i f_i fi 表示缩到 i 的最小代价,枚举从哪一个开始缩
f i = m i n ( f j + s u m i − s u m j − ( i − j ) ∗ a j + 1 ) f_i=min(f_j+sum_i-sum_j-(i-j)*a_{j+1}) fi=min(fj+sumi−sumj−(i−j)∗aj+1)
斜率优化即可
SCOI 2010 股票交易
f i , j f_{i,j} fi,j 表示到第 i 天,有 j 份股票的最大收益,枚举从哪一天转移,当前是买进还是买出,转移前的股票数
买进: f i , j = m a x ( f p , k − ( j − k ) ∗ a p i ) ( p ∈ [ 1 , i − w − 1 ] , k ∈ [ j − a s i , j ) ) f_{i,j}=max(f_{p,k}-(j-k)*ap_i)(p\in[1,i-w-1],k\in[j-as_i,j)) fi,j=max(fp,k−(j−k)∗api)(p∈[1,i−w−1],k∈[j−asi,j))
卖出: f i , j = m a x ( f p , k + ( k − j ) ∗ b p i ) ( p ∈ [ 1 , i − w − 1 ] , k ∈ ( j , j + b s i ] ) f_{i,j}=max(f_{p,k}+(k-j)*bp_i)(p\in[1,i-w-1],k\in(j,j+bs_i]) fi,j=max(fp,k+(k−j)∗bpi)(p∈[1,i−w−1],k∈(j,j+bsi])
p p p 用前缀 m a x max max,每次 f i , j = m a x ( f i , j , f i − 1 , j ) f_{i,j}=max(f_{i,j},f_{i-1,j}) fi,j=max(fi,j,fi−1,j) 即可
然后括号拆开就可以单调队列了
CF1103D Professional layer
题意简述:给 n 个二元组和一个 k。 二元组 ( a i , e i ) (a_i,e_i) (ai,ei)表示第i个位置的权值是 ai,贡献是 ei。 现在对于每个位置可以让它的权值除以它自己一个不超过k的约数,要求从n个数中选择若干个数出来,使得它们的权值在除以约数过后的 g c d gcd gcd为 1,花费的代价是选出来的选择数的个数乘上选出来的所有数的贡献和
考虑到最后的 g c d gcd gcd 一定是一个不超过 1 e 12 1e12 1e12 的数
g c d gcd gcd 可以分解为不超过 12 个约数
又有状压约数集合的影子
令 g c d = p 1 a 1 ∗ p 2 a 2 ∗ . . . ∗ p k a k gcd=p_1^{a_1}*p_2^{a_2}*...*p_k^{a_k} gcd=p1a1∗p2a2∗...∗pkak
对于一个要记入答案的数 v a l val val
令 v a l = t ∗ p 1 b 1 ∗ p 2 b 2 ∗ . . . ∗ p k b k val = t*p_1^{b_1}*p_2^{b_2}*...*p_k^{b_k} val=t∗p1b1∗p2b2∗...∗pkbk
我们选了它更优当且仅当它可以把一个或多个 b i b_i bi 消成 0
这样一来,每个数至少去掉一个 p i p_i pi
因此最多选择 12 个数就可以把 g c d gcd gcd 消为 1
令 f i , S f_{i,S} fi,S 表示选了 i 个数,已经消去的 g c d gcd gcd 的集合为 S S S 的方案数
然后就可以枚举超集转移
CF1106E Lunar New Year and Red Envelopes
f i , j f_{i,j} fi,j 表示到 i,干扰了 j 次的最小贡献
枚举当前干不干扰转移即可,预处理 n x t i nxt_i nxti 表示 i 能转移到哪里
f i , j + w [ i ] − − − f n x t [ i ] , j f_{i,j}+w[i]---f_{nxt[i],j} fi,j+w[i]−−−fnxt[i],j
f i , j − − − f i + 1 , j + 1 f_{i,j}---f_{i+1,j+1} fi,j−−−fi+1,j+1
CF1111D Destroy the Colony
发现如果不限制的话 a n s = f n / 2 ∗ ( n / 2 ) ! ∗ ( n / 2 ) ! ∏ c n t i ans=f_{n/2}*\frac{(n/2)!*(n/2)!}{\prod cnt_i} ans=fn/2∗∏cnti(n/2)!∗(n/2)!
f i f_i fi 表示用所有数组成 i 的方案数,可以背包
考虑预处理答案,每次强制两个不选,然后做一遍,复杂度 O ( 5 2 3 ∗ n ) O(52^3*n) O(523∗n)
然后学了一个叫背包回退的东西
void ins(int x){ for(int i = n/2; i >= x; i--) Add(f[i], f[i-x]);}
void del(int x){ for(int i = x; i <= n/2; i++) Del(f[i], f[i-x]);}
插两个数的答案时暴力删除,变成了 O ( 5 2 2 ∗ n ) O(52^2*n) O(522∗n)
小总结:
总的来说还是一些比较基础的模板类的题
主要复习了一下:
计数 d p dp dp,数位 d p dp dp,单调队列,斜率优化,状压
区间 d p dp dp,数据结构优化,树形 d p dp dp
对四边形不等式的套路有了一些理解
然后有几道巧妙的加状态的题
见识了一些背包回退
深化了状压质因数的套路
在状态定义上的功夫还差得远…