
dp
make_it_for_good
这个作者很懒,什么都没留下…
展开
-
bzoj 1413 [ZJOI2009]取石子游戏 博弈论 dp
果然浙江出神题呀。。。首先有这么一个结论:对于一段区间的石子,在这段区间左侧放一堆石子(个数可以为0)有且仅有一个石子个数使得到的状态为先手必败态。1.因为如果有一种以上的个数,假设有x,y(x<y)x,y(x<y)两个数是先手必败态,那么可以从y转移到x。因此一定小于等于一种。 2.如果没有石子个数为先手必败态,那么每一个必胜态对应转移到的必败态一定是在右侧选一些石子,由于有无穷多个必胜态因此一原创 2016-11-25 09:40:50 · 1748 阅读 · 1 评论 -
bzoj 3072 [Pa2012]Two Cakes dp
这是一个排列因此上下的点是两两对应的。 然后每次找最近的上下对应位置相等的点,在这个位置把上面或下面往后移动一格。这样一定可以得到最优解。 就像这样: 其中红色和蓝色对应相等。 设下面第i个点和上面值对应相等的位置差为val[i]val[i](可以为负) 那么如果当前点为i,那么当前点往前或往后移动后,下一个上下对应位置相等的点的valval 为 val[i]+1val[i]+1 或原创 2016-12-15 20:22:54 · 488 阅读 · 0 评论 -
bzoj 2734 [HNOI2012]集合选数 dp
注意到每一组k2x3y(k%2!=0,k%3!=0)k2^x3^y(k\%2!=0,k\%3!=0) 都是独立的。 那么可以分开算。对于一个k,2x3y2^x3^y 的上界为nk\frac{n}{k},把(x,y)(x,y)看成一个点,形成的图形大概是这样的。 如果一个点选了那么他左边和下边的点不能选。设f[i][j]f[i][j]表示选到第i列,当前列的选法为j的方案数。最后把对于所有k的答案原创 2016-12-15 12:59:42 · 224 阅读 · 0 评论 -
bzoj 2726 [SDOI2012]任务安排 CDQ分治维护凸包 dp
单调处理出第一个串往两边K个能覆盖的字符。 然后对四种字符每种字符做一遍FFT。 对于第一个串,如果这个位置不能匹配当前字符,那该位置为1。 对于第二个串,如果这个位置为当前字符,那该位置为1。 把第二个串反过来和第一个串跑FFT。 答案是在所有FFT中都为0的合法位置个数。#include <bits/stdc++.h>using namespace std;#define N 21原创 2016-12-15 08:57:41 · 647 阅读 · 0 评论 -
bzoj 3120 Line 矩乘 dp
每行结尾连续的1的个数只能是0,1,2。 状态记录一下有几行结尾连续的1的个数为0,几行结尾连续的1的个数为1,当前有多少列为全1。 然后矩乘转移就好了。#include <bits/stdc++.h>using namespace std;#define ll long long#define mod 1000000007int n,P,Q,cnt,ans;ll m;struct原创 2016-12-16 09:43:57 · 455 阅读 · 0 评论 -
bzoj 2090 [Poi2010]Monotonicity 2 树状数组 dp 贪心
设f[i]f[i] 表示到i最长的长度。 然后两个树状数组和一个普通数组分别维护大于,小于和等于。 不会证这个东西。。。#include <bits/stdc++.h>using namespace std;#define N 1100000#define A 1000000int n,K;char s[N];int tr1[N],tr2[N],tr3[N];int a[N],f[原创 2016-12-09 20:26:20 · 510 阅读 · 0 评论 -
bzoj 1481 Navigation Game 决策单调dp
设f[i][j][k(0/1)]f[i][j][k(0/1)] 表示现在在点(i,j),在第i行只走了j一个点,经过的′F′'F'个数奇偶性为k时最少时间。 设l[i][j(0/1)][k(0/1)]l[i][j(0/1)][k(0/1)] 表示在当前行,从i左边的点t出发,经过j个′F′'F',由f[pre][t][k]f[pre][t][k] 更新来的最小时间。 设r[i][j(0/1)][原创 2016-11-25 20:28:10 · 255 阅读 · 0 评论 -
bzoj 1419 概率dp
设f[i][j]表示剩i张R,j张B的期望最大收益。#include <bits/stdc++.h>using namespace std;int n,m;double f[2][5100];int main(){ //freopen("tt.in","r",stdin); scanf("%d%d",&n,&m); for(int i=0;i<=n;i++)原创 2016-11-25 10:55:53 · 273 阅读 · 0 评论 -
bzoj 1415 [Noi2005]聪聪和可可 概率dp
先dijkstra跑出两点间最短路。 g[i][j]g[i][j]表示猫在i,老鼠在j时猫下一步走到的位置。 f[i][j]f[i][j] 表示猫在i,老鼠在j时的期望步数。 f[i][j]f[i][j] 按i到j最短路从小到大转移。#include <bits/stdc++.h>using namespace std;#define N 1100int n,m,S,T,tot,cnt;原创 2016-11-25 10:40:00 · 313 阅读 · 0 评论 -
bzoj 2708 [Violet 1]木偶 dp 贪心
把所有pi排序。最终答案一定是这样的。 就是先一些向左匹配的,再一些向右匹配的。 设f[i]f[i] 表示前i个点的最大个数。 枚举最后一个同向的区间。验证时从小到大枚举验证。#include <bits/stdc++.h>using namespace std;#define N 61int n;int a[N],f[N];int get(int l,int r,int x)原创 2016-12-13 18:00:59 · 396 阅读 · 0 评论 -
bzoj 2560 串珠子 状压dp 容斥
设f[i]f[i] 表示集合i连在一起的方案数,容斥一下就行了。 复杂度O(3n)O(3^n)#include <bits/stdc++.h>using namespace std;#define ll long long#define mod 1000000007int n;int c[21][21],f[(1<<16)+10],sum[(1<<16)+10];int main()原创 2016-12-13 16:21:44 · 489 阅读 · 0 评论 -
bzoj 4145 [AMPPZ2014]The Prices dp
设f[i][j]f[i][j]表示前i个商店买了j集合的物品的最小花费。 g[i][j]g[i][j] 表示第i个商店的买了j集合的物品的最小花费(含路费)。 注意到如果g[i][x]≤g[j][x]g[i][x]\le g[j][x] 那么去i买x的物品一定不比去j买x的物品差。 因此对于一种物品集合只需要有一个商店转移时转移这个集合就行。 复杂度O(n2m+3m)O(n2^m+3^m)原创 2016-12-22 09:52:38 · 356 阅读 · 0 评论 -
bzoj 4197 [Noi2015]寿司晚宴 dp 容斥
注意到小于n√\sqrt{n} 的质数最多有8个。而大于n√\sqrt{n} 的质因子每个数至多有1个。 因此状压<n√<\sqrt{n} 的质数。 设f[i][j]f[i][j] 表示A选的<n√<\sqrt{n} 的质数集合为i的子集,B选的<n√<\sqrt{n} 的质数集合为j的子集的方案数。预处理num[i][j]num[i][j] 表示<n√<\sqrt{n} 的质因子集合为i,>n原创 2016-12-22 13:52:12 · 329 阅读 · 0 评论 -
4574 [Zjoi2016]线段树 dp
这题的前缀和开始没有想到。 如果不用前缀和状态是五维的。。。由于数据随机所以不会有两个相等的数。 最终答案是求每个数在所有方案下的取值的和。 对于每个数dp一下,设当前数为val,区间[L,R]为以当前数为最大值的最大区间。 设f[i][l][r]f[i][l][r] 表示前i个询问,区间[L,R]剩余的小于等于当前数的区间为[l,r]的方案数。 然后转移时处理一个前缀和可以O(1)转移。原创 2016-12-23 07:55:47 · 372 阅读 · 0 评论 -
bzoj 4008 [HNOI2015]亚瑟王 期望dp
先考虑这么一个式子: Pr第2次选2=Pr第2次不选1∗Pr第1次不选2∗Pr选2Pr_{\text{第2次选2}}=Pr_{第2次不选1}*Pr_{第1次不选2}*Pr_{选2} 其中Pr表示概率。 这个式子是错的,因为 第1次不选2和第2次不选1的概率不是独立的。 所以直接算的方法gg了。 设f[i][j]f[i][j] 表示前i个点有j个被选过的概率。 g[i]g[i] 表示点i被选原创 2016-12-20 21:27:36 · 505 阅读 · 0 评论 -
bzoj 4000 [TJOI2015]棋盘 dp 矩乘
逗比题面,毁我青春 行列编号从零开始。。。然后我以为那个点在最上面那排。。。 妈蛋那样要记两排状态!!! 点在中间那排的话记一排状态矩乘转移就行了。#include <bits/stdc++.h>using namespace std;#define ui unsigned intint n,m,p,K;int a[4][7],able[71];ui ans;struct Matr原创 2016-12-20 18:42:04 · 591 阅读 · 0 评论 -
bzoj 3851 2048 dp
一开始sb看错题,没看见两个相等的数拼在一起。 如果只有两个相等的数能拼在一起,那只有2的整数次幂有用。 设f[i][j]f[i][j] 表示选了202^0 到 2i2^i 的数和为j的方案数。 注意到只要和大于等于2048就有解,因此第二维只需要到2048(表示大于等于2048)。 然后对组合数求一个后缀和,当第二维大于2048时直接用后缀和转移。#include <bits/stdc++原创 2016-12-20 12:40:55 · 529 阅读 · 0 评论 -
bzoj 3611 [Heoi2014]大工程 虚树 dp
直接上虚树dp一下就好了。。。#include <bits/stdc++.h>using namespace std;#define N 1100000#define ll long longint n,Q,cnt,top,tot,m,tim;int head[N],nex[N<<1],to[N<<1],st[N];int a[N],pos[N],fa[N][21],deep[N],bj原创 2016-12-20 09:37:46 · 344 阅读 · 0 评论 -
bzoj 3598 [Scoi2014]方伯伯的商场之旅 数位dp
当位置向后移动时,可以发现答案加上前面一段所有数字之和减去后面一段所有数字之和。 然后前面一段所有数字之和单调不减,后面一段所有数字之和单调不增。 为了避免重复找最前面的满足的点。设答案的位置为a1,a1的下一个位置为a2。 应该选取的位置满足s1<a1+a2+s2 s1+a1≥a2+s2s1<a1+a2+s2\ \ \ \ \ s1+a1\ge a2+s2 然后对左边右边分别数原创 2016-12-20 08:39:33 · 748 阅读 · 0 评论 -
bzoj 3572 [Hnoi2014]世界树 虚树 dp
先建出虚树(似乎虚树可以不写重新标号) dfs两次维护f[x]f[x] 在x的子树中距x最近的选中的点,g[x]g[x] 整棵树中距x最近的选中的点。 考虑虚树中的每一条边,这条边上的所有不在虚树上的点以及他的子树只能选这条边两端的虚树上的点的g[x]g[x]。 求出分界位置。对于求一条链上点的子树的大小之和,可以倍增维护一个点到祖先的size之和,假设求链fa[x]到fa[y]上点的子树原创 2016-12-19 18:41:19 · 280 阅读 · 0 评论 -
bzoj 3566 [SHOI2014]概率充电器 概率dp
题里那个直接充电和间接充电是一样的。。。 除0挂了半天还以为是卡精。。。设f[i]f[i] 表示i和i的子树使点i充电的概率。 设g[i]g[i] 表示除掉i的子树的剩余的部分把i的父亲充电的概率。 转移看代码吧。。。。#include <bits/stdc++.h>using namespace std;#define N 510000#define eps 1e-15int n,t原创 2016-12-19 13:33:17 · 385 阅读 · 0 评论 -
bzoj 4321 queue2 dp
设f[i][j][0/1]f[i][j][0/1] 表示前i个数有j个非法的,i是否与i-1相邻的方案数,转移看代码吧。。#include <bits/stdc++.h>using namespace std;#define N 1100#define mod 7777777#define ll long longint f[N][N][2],n;void upd(int &x,int原创 2016-12-22 17:58:13 · 395 阅读 · 0 评论 -
bzoj 4318 OSU! 概率dp
这道题只是想告诉我们只有两个期望无关时才可乘,因此平方的期望不等于期望的平方。。。 需要维护f1[i]表示到i连续的个数的期望,f2[i]表示到i连续的个数平方的期望,f3[i]表示到i连续的个数立方的期望#include <bits/stdc++.h>using namespace std;#define N 110000int n;double f1[N],f2[N],f3[N],pr原创 2016-12-22 15:02:12 · 321 阅读 · 0 评论 -
bzoj 1296 [SCOI2009]粉刷匠 dp
设g[i][j][k]表示第i个串前j位刷k次最多的正确格子。 设f[i][j]表示前i个串刷j次最多的正确格子。 第一次没有看见一个格子只能被刷一次。。。#include <bits/stdc++.h>using namespace std;int n,m,K,ans;char s[51];int sum[51][51][2],g[51][51][51],f[51][2600];vo原创 2016-11-24 18:54:11 · 291 阅读 · 0 评论 -
bzoj 1226 [SDOI2009]学校食堂Dining 状压dp
设f[i][j][k]表示当前最早的没打饭的人为i,i后面的7个人打过的状态为j,上一个打饭的人为i+k的方案数。 不过需要注意上一个打的人和当前人的差最大是8。。。 然后转移时可能是后面的人打饭或当前人打饭。 注意判一下状态非法。。。#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#incl原创 2016-11-24 16:03:17 · 384 阅读 · 0 评论 -
bzoj 1087 [SCOI2005]互不侵犯King 状压dp
sb状压,输int错了一次,没救了。。。#include <bits/stdc++.h>using namespace std;#define ll long long#define N (1<<9)+10int n,m;bool g[N][N];ll f[11][110][N],ans;int num[N];int check(int x,int y){ for(int原创 2016-11-24 13:27:43 · 301 阅读 · 0 评论 -
bzoj 1512 [POI2006]Pro-Professor Szu tarjan dp
先tarjan缩点,然后拓扑dp。 似乎有一些细节。。。#include <bits/stdc++.h>using namespace std;#define N 1000010#define inf 36501int n,m,tot,top,cnt,scc,ans;int head[N],nex[N],to[N];int deep[N],low[N],st[N],bel[N];bo原创 2016-11-29 16:40:05 · 522 阅读 · 0 评论 -
bzoj 1505 [NOI2004]小H的小屋 dp
设g[i][j]g[i][j] 表示下面长度为i的一段放j个的最小花费。 那么g[i][j]=k2∗(i/j+1)2∗(i%j)+k2∗(i/j)2∗(j−i%j)g[i][j]=k2*(i/j+1)^2*(i\%j)+k2*(i/j)^2*(j-i\%j) (使所有尽量相等时花费最小)设f[i][j][k]f[i][j][k] 表示到i,上面有j个矩形,下面有k个矩形的最小花费。 然后转移时原创 2016-11-29 13:49:40 · 515 阅读 · 0 评论 -
bzoj 2806 [Ctsc2012]Cheat 后缀自动机 单调队列优化dp
首先把字典中所有的串接在一起,两两间用非法字符隔开,跑一个后缀自动机(感觉这样比广义后缀自动机好写一些?) 然后对于要匹配的串在后缀自动机里跑一遍得到每个点向前能匹配的最大长度v[i]。求的东西可以二分答案。然后dp,设f[i]表示到i能匹配上的所有子串最大长度。f[i]=⎧⎩⎨max(f[i],f[j])(j∈[0,i−1])max(f[i],f[j]+v[i])(j∈[0,i−v[i]])max原创 2016-10-24 10:58:35 · 313 阅读 · 0 评论 -
bzoj 4380 dp
最终每一个点的值一定为某个ci,将ci离散化。 区间dp,设f[i][j][k]表示当区间 [ i , j ] 中的最小值为k时的最大收益。转移:f[i][j][k]=max(f[i][x-1][q1]+f[x+1][j][q2]+cnt*k)(q1,q2>=k) val为左端点在 [i,x] 且右端点在 [x,i] 且值大于等于k的区间个数。时间复杂度O(n^3*m)#include <bit原创 2016-08-20 19:57:04 · 500 阅读 · 0 评论 -
bzoj 4254 树形dp
题意:给n个点,第i个点坐标(xi,yi),保证xi<xi−1x_i<x_{i-1} 且相邻两个点的y坐标不同。对于两个y坐标相等的点,如果两个点中间所有点的y坐标小于两个点的y坐标,那么两个点可以连一条边。给出m,k。求连m条边,使每个点上方的边数小于k的最大边长和,无解输-1。每个点最多向右连出一条边。两条边的位置关系只可能是包含或没有交集。 那么这就是很多棵树。建出树,树形dp,设f[i][原创 2016-08-23 17:01:18 · 342 阅读 · 0 评论 -
bzoj 3864 dp套dp
题意:给一个长度为n(n<=15)n (n<=15) 的DNA串ss,对于[0,n][0,n] 之间的每一个整数xx 求有多少长度为mm 的DNA串与 ss 的lcs长度为 xx 。考虑dp求lcs的转移分两种: 1.f[i][j]=max(f[i−1][j],f[i][j−1])(S1[i]!=S2[j])1. f[i][j]=max(f[i-1][j],f[i][j-1]) (S1[i]!=原创 2016-09-12 10:22:21 · 1003 阅读 · 0 评论 -
bzoj 4347 dp
设f[i][j][k]表示前i堆石子,扔掉堆数%d=j,剩下的石子异或和为k的方案数。 将个数从小到大排序,由于异或,所以k只需枚举到O(该堆个数)。 时间复杂度O(md)滚动数组内存会暴,每次用k和k^a[i]互相更新。#include <bits/stdc++.h>using namespace std;#define N 1048576#define mod 1000000007i原创 2016-08-20 16:24:20 · 779 阅读 · 0 评论 -
bzoj 3812 状压dp 容斥原理
题意:一个n个点m条边的有向强连通图,去掉一些边使其仍然强连通,求方案数。以前做的题,现在看已经不知道自己在写什么了。写一点题解。如果一个图缩点后变成一个有多个点的DAG,那么这玩意一定不连通。设f[i]f[i] 表示拆边使集合i强连通的方案数,g[i]g[i] 表示i集合的点缩点后成为奇数个彼此没有边的点的方案数,p[i]p[i] 表示缩成偶数个彼此没有边的点的方案数。对于g[i]g[i] 和 p原创 2016-08-26 20:23:50 · 1200 阅读 · 1 评论 -
bzoj 1021 dp
题意:三个人,A欠B,B欠C,C欠A。给出每个人拥有的钞票种类和数量,求三个人最少操作多少次。dp,设 f[i][j][k]表示到第i种钱,第一个人有j块,第二个人有k块时最少操作次数。只有一个人把第i种钱给其他两个人或两个人把第i种钱给剩下一个人两种情况。dp时讨论一下。#include <bits/stdc++.h>using namespace std;int p[11]={0,100,5原创 2016-08-18 11:31:14 · 618 阅读 · 0 评论 -
bzoj 2669 状压dp 容斥原理
题意:一个n∗mn*m的矩阵,填1到n∗mn*m 的数,有的位置必须小于八连通的相邻位置,求方案数。设f[i][j]f[i][j] 表示填到i,已经填完的局部最小值的集合为j的方案数。 设cnt[j]cnt[j] 表示对于局部最小值的集合j,不与除j外局部最小值的集合相邻的点的个数。f[i][j]=f[i−1][j]∗(cnt[j]−i+1)+∑f[i][j−k]f[i][j]=f[i-1][j]原创 2016-08-27 19:22:12 · 771 阅读 · 0 评论 -
bzoj 1563 [NOI2009]诗人小G 四边形不等式 决策单调dp
正常转移f[i]=max(f[i′]+(L−(sum[i]−sum[i′]+i−i′−1))p)f[i]=max(f[i']+(L-(sum[i]-sum[i']+i-i'-1))^p) 这个东西好像满足四边形不等式。因此决策单调。 设g[i]表示点i的决策区间的左端点。 cal(i,j)表示用i更新j的答案。 维护一个g[i]单调递增的队列,每次把决策区间在当前点之前的队首扔掉。然后用队首原创 2016-11-30 19:45:45 · 426 阅读 · 0 评论 -
bzoj 1801 [Ahoi2009]chess 中国象棋 dp
要求就是每行每列个数<=2 设f[i][j][k]f[i][j][k] 表示到第i行,有j列有0个,k列没有的方案数。 然后当前行可以放一个或两个。#include <bits/stdc++.h>using namespace std;#define N 110#define mod 9999973#define ll long longint n,m;int f[N][N][N],原创 2016-11-30 21:04:37 · 283 阅读 · 0 评论 -
bzoj 1080 [SCOI2008]劣质编码 最短路
这题可以用一种迷之暴力水过,不过并不知道复杂度,听说跑的挺快的。。。 算了,说正解。。。 当要求有两种解码方式时可以这样做: 把两个串中长的那个当成模板串,短的那个当成匹配串。 设f[i][j]f[i][j] 表示模板串当前为i,匹配串匹配到j,模板串的最短长度。 然后枚举匹配串下一个接哪个串,如果接完后比模板串长那么互换两个串。 这两个串必须从开始时就接不同的串。然后三个串的情况。一个原创 2016-11-24 12:30:53 · 1058 阅读 · 0 评论 -
bzoj 1079 [SCOI2008]着色方案 dp
设f[][][][][][]表示剩余个数为1~5的颜色的种类数和上次选的颜色的剩余个数。#include <bits/stdc++.h>using namespace std;#define mod 1000000007#define ll long longll f[16][16][16][16][16][6],num[6];bool vis[16][16][16][16][16][6]原创 2016-11-23 18:38:40 · 353 阅读 · 0 评论