DP泛做
[CF455 A] Boredom
题目大意
给定n个数,每次任选一个数ai,得到ai的得分,同时ai−1和ai+1都消失,无法再被选取,询问最大得分和
题解
dp[i,1]:[1,i]的数都被处理完,i这个数被选的最大得分和
dp[i,0]:[1,i]的数都被处理完,i这个数未选的最大得分和
dp[i,1]=dp[i−1,0]dp[i,0]=max{dp[i−1,1],dp[i−1,0]}
CODE
[CF629 D] Babaei and Birthday Cake
题目大意
给定n块蛋糕,要求
1.编号小的放在编号大的上
2.体积严格递增
题解
dp[i]:=max{dp[j]+v[i]} (v[i]>v[j])
对v[i]离散化后,权值线段树优化一下就好了
CODE
[CF631 E] Product Sum
题目大意
给定n个数的序列,这个序列的价值为∑i∗ai,可以移动一个数,使新的序列价值最大,询问最大价值
题解
[CF613 D] Kingdom and its Cities
题目大意
给定一棵树,多次给定一些关键点询问最少拆掉多少非关键点使得任意两关键点间不可到达
题解
建立虚树,树形DP自己YY一下就好啦
CODE
[BC75 C] King’s Order
题目大意
国王最多连续说一个字母3次,给定话的长度n询问方案数
题解
dp[i,j]:说话长度为i最后一个字母重复j次的方案数
dp[i,1]=(dp[i−1,1]+dp[i−1,2]+dp[i−1,3])∗25
dp[i,2]=dp[i−1,1]
dp[i,3]=dp[i−1,2]
dp[1,1]=26
ans=dp[n,1]+dp[n,2]+dp[n,3]
CODE
[BC71 C] KK’s Number/[BZOJ2091] [Poi2010]The Minima Game
题目大意
每次给n个数,AB轮流取,每次得分为取的数中最小的那个
两个人的策略都是自己−对方得分最大,A先取,询问A−B的最大得分
题解
先手和后手,当一个人取完他之前的先手就变成对方的先手了,并且两人的策略相同,所以设计一个人的DP状态即可
dp[i]:A最后取,前i数字的最大分差
dp[i]=max(x[j+1]−dp[j])
CODE
[BZOJ2302] [HAOI2011]Problem c
题目大意
有n个人和n个位置,要求给每个人安排一个位置ai,这样形成一个序列{a}, 每个人依次走到ai,若ai已经有人则尝试ai+1,直至有空位,若到n一直没有,则称这个序列不合法 已经确定了序列的一部分,询问合法序列数
题解
合法与人去坐的先后顺序无关
一个序列合法,表明对于每一个编号i都有,∑ij=1num[j]≥i
dp[i,j]:≤i的编号,在序列中已经出现了j次的方案数
dp[i,j]=∑j−i+1k=cnt[i]dp[i−1,j−k]∗Ck−cnt[i]sum[i]−cnt[i]−(j−k)
sum[i]表示可以编号≤i的人数,即n−已经确定编号且>i的人数
cnt[i]表示确定编号为i的人数
j−k≥i−1且k≥cnt[i]
sum[i]−cnt[i]−(j−k):可以放i的位置−已经定下来的−放在≤i−1的位置的,也就是还能放的位置数
k−cnt[i]:打算放i的位置数
一开始交,组合数求错了…
c[i,j]=c[i−1,j−1]+c[i−1,j]
CODE
[BZOJ3864] Hero meet devil
题目大意
给你一个只由AGCT组成的字符串S(|S|≤15),对于每个1≤i≤|S|
询问有多少个只由AGCT组成的长度为m(1≤m≤1000)的字符串T,使得LCS(S,T)=i
题解
[BZOJ3233] [Ahoi2013]找硬币
题目大意
构造一个硬币序列\{a_i\}且a_1=1,a_i是a_j的整数倍,使得购买n种物品所需硬币数量最小(每个物品必须用刚好满足的钱数购买),询问最小数量
题解
性质:当我们知道最大面值的硬币了,我们就能知道这个序列的其他面值是最大面值的因子了,且购买物品时是贪心购买
dp[i]:用最大面值为i的硬币序列购买所有物品的最小硬币数
dp[i]=min\{dp[j]-\sum_k\frac{x[k]}{i}*(\frac{i}{j}-1)\}~~~~(j是i的因子)
若i/j不是质数,即=p_1*p_2,那么我们从面值为j*p_1那里转移是一定更优的,因为最大面值大了,且与j是倍数关系,一定包含j的硬币序列
dp[i]=min\{dp[i/j]-\sum_k\frac{x[k]}{i}*(j-1)\}~~~~(j\in prime)
CODE
[BZOJ4069] [Apio2015]巴厘岛的雕塑
题目大意
有那个点(有顺序),每个点有权值,要求分成m段(m\in[A,B]),使得每组权值和的or值最小
题解
因为是位运算,所以我们贪心从高到低来求答案
dp[i,j]:前i个分成j组且满足高位已经定下来的条件,这一位是否为0
因为or运算如果最后结果为0那么必须都为0所以比较好求
sum=sum[i]-sum[k]
dp[i,j]=\begin{cases}1&dp[k,j-1]=1且sum\&amp;(1<<(pos-1))=0且sum|ans=ans\\0\end{cases}
判断在[A,B]范围内是否满足条件即可
复杂度O(30*N^3)
对于最后一个subtask,A=1
dp[i]:前i个数,满足前面确定的条件下最少分多少组
sum=sum[j]-sum[i]
dp[i]=\min\{dp[j]+1\}~~~(sum\&amp;(1<<(pos-1))=0)且(sum|ans=ans)
CODE
[BZOJ4380] [POI2015]Myjnie
题目大意
有n家店,有m个人来购买物品,第i个人购买l[i]到r[i]的店铺中花费最小的l物品,若这个物品价值>val[i]则不进行购买
构造每家店的价格使得所有店的收益之和最大
有SPJ
题解
[BZOJ1026] [SCOI2009]windy数
题目大意
定义windy数为相邻两位的差都\ge 2的数
询问[A,B]内windy数数量
题解
数位DP
dp[i,j]:i位最高位为j的windy数个数
等价于求[1,A]的windy数个数
假设A的最高位为a_1,后面同理
首先是位数比A小的\sum_{i=1}^{len[a]-1}dp[i,j](1\le j\le9)肯定要计入答案
其次是位数于A相同,但最高位比a_1小的\sum_{i=1}^{a_1-1}dp[len[a],i]
最后是位数与A相同最高位与a_1相同,第二位比a_2小的且满足windy数的个数
\sum_{j=0}^{a_2-1}dp[len[a]-1,j](|a_1-j|\ge2)
也就是我们依次让后面那些位与A那一位的数相同
当|a_i-a_{i-1}|< 2时就停止继续将后面的计入答案了
最后注意一下,这种统计方法是无法将A本身计入的,所以我们最后答案是count[b+1]-count[a]
CODE
[BZOJ1833] [ZJOI2010]count 数字计数
题目大意
询问[A,B]的所有数中0~9各出现多少次
题解
dp[i,j,k]:表示有i位最高位为j,k出现了多少次
dp[i_1,i_2,i_3]=\sum_{i_4=0}^{9}dp[i_1-1,i_4,i_3]+10^{i_1-1}(i_3=i_2)
dp[i_1,i_2,i_3]=\sum_{i_4=0}^{9}dp[i_1-1,i_4,i_3]~~~~~~~~~~~~~~~(i_3\not=i_2)
统计[1,A]时,先ans[j]=\sum_{i=1}^{len[A]-1}\sum_{k=1}^{9}dp[i,k,j]
再ans[j]+=\sum_{i=1}^{a_1-1}dp[len[A],i,j]
最后ans[j]+=\sum_{k=1}^{len[A]-1}\sum_{i=0}^{a_k-1}dp[k,i,j]
并且ans[x[i]]+=A[i+1..len[A]]
最后不要输出空格…..
CODE
[BC66 C] GTW likes czf
题目大意
给定区间[L,R]和两个数G,T,从[L,R]和G,T中各自任取一个数A和B,得到C=A@B,询问有多少种C
定义@运算为A@B=((A\&amp;B)|B)^B)
题解
打表可知,打表可知啊A@B=A
^
B
0
^
位运算的每一位都不干扰,所以一个数亦或任意数的值都是不同的
所以
ans=(r−l+1)∗2−亦或相同个数
亦或相同个数=[i
^
G=j
^
T的个数]
然后变下形(这个试一下就好了,不证了..),等价于i
^
j=S
^
T
定义count(x,y)=∑xi=1∑yj=1[i
^
j=P]
就是要求count(r,r)−count(l−1,r)−count(l,r−1)+count(l−1,l−1)
当然count(l−1,r)=count(l,r−1)...
我们考虑数位DP来求count(i,j)
设dp状态为dp[i,j,k]:到第i位,状态j,k所代表的方案数
j,k有四种状态
0,0:表示第i位第一个数不卡上界,第二个数不卡上界
0,1:表示第i位第一个数不卡上界,第二个数卡上界
1,0:表示第i位第一个数卡上界,第二个数不卡上界
1,1:表示第i位第一个数卡上界,第二个数卡上界
我们认真讨论一下
x[i]:表示第一个数二进制下第i位,y[i],p[i]同理
(i,j,k)表示x[?]=i,y[?]=j,p[?]=k
⎧⎩⎨⎪⎪⎪⎪0^0=01^1=01^0=10^1=1
(0,0,0)
dp[i,1,1]=dp[i+1,1,1]dp[i,0,0]=dp[i+1,0,0]∗2dp[i,1,0]=dp[i+1,1,0]dp[i,0,1]=dp[i+1,0,1]
(0,0,1)
dp[i,1,1]=0dp[i,0,0]=dp[i+1,0,0]∗2dp[i,1,0]=dp[i+1,1,0]dp[i,0,1]=dp[i+1,0,1]
(0,1,0)
dp[i,1,1]=0dp[i,0,0]=dp[i+1,0,0]∗2+dp[i+1,0,1]dp[i,1,0]=dp[i+1,1,0]+dp[i+1,1,1]dp[i,0,1]=dp[i+1,0,1]
(0,1,1)
dp[i,1,1]=dp[i+1,1,1]dp[i,0,0]=dp[i+1,0,0]∗2+dp[i+1,0,1]dp[i,1,0]=dp[i+1,1,0]dp[i,0,1]=dp[i+1,0,1]
(1,0,0)
dp[i,1,1]=0dp[i,0,0]=dp[i+1,0,0]∗2+dp[i+1,1,0]dp[i,1,0]=dp[i+1,1,0]dp[i,0,1]=dp[i+1,0,1]+dp[i+1,1,1]
(1,0,1)
dp[i,1,1]=dp[i+1,1,1]dp[i,0,0]=dp[i+1,0,0]∗2+dp[i+1,1,0]dp[i,1,0]=dp[i+1,1,0]dp[i,0,1]=dp[i+1,0,1]
(1,1,0)
dp[i,1,1]=dp[i+1,1,1]dp[i,0,0]=dp[i+1,0,0]∗2+dp[i+1,1,1]+dp[i+1,1,0]+dp[i+1,0,1]dp[i,1,0]=dp[i+1,1,0]dp[i,0,1]=dp[i+1,0,1]
(1,1,1)
dp[i,1,1]=0dp[i,0,0]=dp[i+1,0,0]∗2+dp[i+1,0,1]+dp[i+1,1,0]dp[i,1,0]=dp[i+1,1,0]+dp[i+1,1,1]dp[i,0,1]=dp[i+1,0,1]+dp[i+1,1,1]
然后上面的转移找一下规律,会好写一点
初值为dp[63,1,1]=1因为3个数这位都是0
CODE
[BZOJ3209] 花神的数论题
题目大意
定义sum(i):i的二进制中有多少个1
求∏ni=1sum(i)(mod10000007)
i≤1015
题解
sum(i)的取值最多就60个,数位dp求出来,快速幂计算一下
CODE
[BZOJ3329] Xorequ
题目大意
给定方程
x
^
1.[1,n]的数中有多少是方程的解
2.[1,2n]的数中有多少是方程的解(mod1e9+7)
题解
x
^
那么
x+2x=3x=x
^
2x
同时2x=x<<1
也就是说x在二进制下任意两个1都不相邻
第一问数位DP解决即可
第二问是斐波那契数列…矩阵搞之
CODE
[BC70 C]Jam’s maze
题目大意
给定一个正方形矩阵,每个点代表一个大写字母,从左上角走到右下角,且只能向下或向右走,询问走出的路径是回文的条数
(mod5201314)
FFFF!
题解
dp[x1,y1,x2,y2]:(1,1)−>(x1,y1)=(x2,y2)<−(n,n)的方案数
dp[x1,y1,x2,y2]+=⎧⎩⎨⎪⎪⎪⎪⎪⎪dp[x1−1,y1,x2+1,y2]dp[x1−1,y1,x2,y2+1]dp[x1,y1−1,x2+1,y2]dp[x1,y1−1,x2,y2+1] (t[x1,y1]=t[x2,y2])
但空间时间都承受不了,所以我们考虑优化无用状态
当我们知道走多少步之后,只需知道一个坐标值就可以知道另一个了,这样优化掉一维
走多少步那一维可以滚动数组优化掉
CODE
[BZOJ4011] [HNOI2015]落忆枫音
题目大意
给定一张DAG图(1的入度为0),和一条有向边,询问新图中以1为根的树形图数量(mod1e9+7)
题解
首先不加入新边时DAG图的树形图数量为∏ni=2deg[i](deg[i]:表示i的入度)
加入之后我们要减去由这条边出现而形成的环的方案数,即为
dp求解
若存在路径pre1/2/...→i那么
∑s∈y→pre1的路径∏j∉s且j≠1deg[j]
∑s∈y→pre2的路径∏j∉s且j≠1deg[j]
…
∑s∈y→i的路径∏j∉s且j≠1deg[j]
dp[i]=∑存在j→idp[j]deg[i]
dp[y]=∏ni=2deg[i]deg[y]
注意连边到根节点1的情况要特判一下
贴上求拓扑序的代码,好久不写手好生
procedure dfs(a,b:longint);
var tt:longint;
begin
vis[a]:=1; tt:=w[a,2]; if (a=b) then tt:=0;
while (tt<>0) do
begin
if (vis[w[tt,1]]=0) then dfs(w[tt,1],b);
tt:=w[tt,2];
end;
inc(len); x[len]:=a;
end;
[BZOJ3727] PA2014 Final Zadanie
题目大意
给定一棵树,边长都为1,b[i]=∑nj=1dis[j,i]∗a[j],给出所有b[i],询问所有a[i]
题解
b[1]=∑dep[i]∗a[i]
b[i]=b[fa[i]]+size[1]−2∗size[i]
b[i]−b[fa[i]]=size[1]−2∗size[i]
size[i]=12size[1]−(b[i]−b[fa[i]])2
a[i]=size[i]−∑size[son[i]]
线性得到
a[i]与size[1]的函数关系:a[i]=k[i]1∗size[1]+k[i]2
b[1]=∑(dep[i]∗k[i]1)∗size[1]+∑dep[i]∗k[i]2
解出size[1]
size[i]=12size[1]−(b[i]−b[fa[i]])2
size[i]=a[i]+∑size[son[i]]
a[i]=size[i]−∑size[son[i]]
貌似数学推导更多些,没有太强的树形DP的感觉
CODE
[BZOJ3257] 树的难题
题目大意
给定一棵树,有边权,点有0,1,2三种颜色,要求删掉一些边使得形成的森林中的每棵树中都不含0节点或至多一个1节点,询问最小代价
题解
f[i]:i的子树中没有0节点 g[i]:i的子树中没有1节点 h[i]:i的子树中有1个1节点
若x[i]=0 f[i]=inf g[i]=∑jming[j],f[j]+w[i,j],h[j]+w[i,j] h[i]=minh[j]+∑k≠jming[k],f[k]+w[i,k],h[k]+w[i,k]
若x[i]=1 f[i]=∑jminf[j],g[j]+w[i,j],h[j]+w[i,j] g[i]=inf h[i]=∑jming[j],f[j]+w[i,j],h[j]+w[i,j]
若x[i]=2 f[i]=∑jminf[j],g[j]+w[i,j],h[j]+w[i,j] g[i]=∑jming[j],f[j]+w[i,j],h[j]+w[i,j] h[i]=minh[j]+∑k≠jming[k],f[k]+w[i,k],h[k]+w[i,k]
CODE
[BZOJ1040] [ZJOI2008]骑士
题目大意
给定一个基环树林,每个点上有权值,要求选择一个权值和最大的点集,要求点集中的任意两个点之间不能直接相连
题解
拆环,讨论,树形DP
CODE
[BZOJ4033] [HAOI2015]T1
题目大意
给定一棵树,要求将m个点染黑,这棵树的权值为所有黑点两两间距离和+所有白点两两间距离和,询问最大权值
题解
设计dp状态
一开始我设dp[i,j]表示以i为根的子树有j个点被染黑,该子树的最大权值
转移非常经典就不说了,但是我越来越觉得这个不具有最优子结构
设dp[i,j]表示以i为根的子树有j个点被染黑,这棵子树中所有边对整棵树的贡献值
这个在树上做背包算当前统计的边的贡献即可了
get到了树上背包的写法 果然还是too naive...
CODE
[BZOJ3829] [Poi2014]FarmCraft
题目大意
给定一棵树,从1号节点出发对树进行欧拉遍历,每到达一个点这个点就开始装MC,每个点装MC的时间不同,最后回到1号节点装MC,求所有人都能联机的最少时间
题解
设f[i]:表示以i为根的子树遍历后还需f[i]的时间才能安装完
f[i]=min{∑j∈son[i]max{0,f[j]−∑k在j后被遍历(size[k]∗2+1)}}+max{0,val[i]}
当f[j]−size[k]∗2+1+f[k]≥f[k]−size[j]∗2+1+f[j]
交换两棵子树
[BZOJ3831] [Poi2014]Little Bird
题目大意
要从第一棵树跳到第n棵,每次可以从第i棵跳到第i+k棵,若跳到的树的高度≥原树高度,疲劳值+1,询问最小疲劳值
题解
dp[i]=max{dp[j]+[x[j]≤x[i]]} (i−k≤j<i)
考虑单调队列优化一下
疲劳相同取高的
疲劳不同取疲劳值小的的
第一个显然,第二个我们可以讨论一下
1.一样高取小的
2.小的高取小的
3.小的矮取小的(花费1之后要么和花费多的一样要么和花费多的小,并且相当于高度变为正无穷了)
CODE