前言:最近刷了一些水题…
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
对四边形不等式的套路有了一些理解
然后有几道巧妙的加状态的题
见识了一些背包回退
深化了状压质因数的套路
在状态定义上的功夫还差得远…