动态规划
青烟绕指柔!
我不怕千万人阻挡,只怕自己投降。
展开
-
Junior Mathematician
题目链接:Junior Mathematician不难想到可以数位dp去做。但是直接令状态为前 i 位,当前数位和为 j ,数字值为 k ,f(x)的值为 l 的个数复杂度过高。我们可以发现数字值和 f(x)的值可以一起计算,然后减少一维状态即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace原创 2021-11-30 22:06:17 · 200 阅读 · 0 评论 -
小 A 的卡牌游戏
题目链接:小 A 的卡牌游戏考虑 “2pick” 问题,可以贪心,假设全部选a,然后按照 b - a 的差值,从大到小来选择剩下的。同理,现在变成了 “3pick” 问题,所以我们可以控制c的选或者不选,然后附带一个有关c选择个数的 dp 即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace st原创 2021-11-15 17:06:41 · 3387 阅读 · 0 评论 -
TRESNJA
题目链接:TRESNJA每次数位dp的时候,维护总和以及总个数。然后对每一位枚举当前要选某个数字,然后数字选择的个数即可算出增加的贡献。为了避免重复,当前选择的数字一定要和之前不同。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=20;int a[N],l,r原创 2021-07-02 23:01:19 · 86 阅读 · 0 评论 -
最大收益
题目链接:最大收益假设我们选择了一个集合的物品,为了使得价值最大,我们肯定是按照 R 从小到大选择。然后我们可以先按照R从小到大sort。考虑dp,dp[i][j] 前 i 个物品选择了 j 个的最大值。但是我们发现转移是有后效性的,因为不知道后面选择了多少个,但是我们从后往前dp,就知道当前的转移了。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define in原创 2021-06-28 15:23:08 · 124 阅读 · 0 评论 -
Video Game G
题目链接:Video Game G用AC自动机优化状压dp,然后记得统计一下fail树上的值。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=3010;int n,m,dp[1010][N],res; char str[N];int ed[N],fail[N原创 2021-06-23 19:51:28 · 96 阅读 · 0 评论 -
Byfibonacci
题目链接:Byfibonacci这个题有一个trick,就是每个数字,不可能不由小于本身的最大两个fib组成。然后我们每次就枚举整个序列最大值是小于本身的第一个fib,还是第二个fib即可。但是我们要注意,次大的fib会计算重复。但是又最多用两次,所以可以容斥减掉。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing n原创 2021-06-20 20:57:09 · 368 阅读 · 0 评论 -
[清华集训2012]串珠子
题目链接:[清华集训2012]串珠子因为得到的是一个连通图,所以我们可以考虑用任意连边的方案数减去不连通的方案数。对于不连通的方案数,我们可以让一个子集连通,然后另一个子集随意连边。但是这样子集转移的时候是会计算重复的,所以我们可以考虑固定一个点,然后对于其他点来说就是与固定的点连通,然后不与固定的点连通。固定一个点也就是减去一个点,具体实现可以通过异或掉最低位来解决。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#includ原创 2021-03-17 09:48:47 · 197 阅读 · 0 评论 -
单词
题目链接:单词令 dp[i] 为以i结尾要选一个区间的方案数。然后我们可以知道当前要包含的位置,然后从前面更新,然后前面是一个前缀和的和。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=1e6+10;const int base=131,mod=99824353原创 2021-03-07 23:13:28 · 64 阅读 · 0 评论 -
Codeforces - Cheap Dinner
题目链接:Codeforces - Cheap Dinner因为物品直接的关系都是相邻的关系,不成环,所以可以dp。然后对于每个物品能选的其实是多个区间,且区间个数不超过m之和。所以维护区间min,然后区间查询即可。可以用线段树优化。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;c原创 2021-02-16 20:54:50 · 243 阅读 · 0 评论 -
Kotori
题目链接:Kotori考虑dp,dp[i][j] 第 i 回合,j 是否可以活下来。然后我们可以发现每个人在某个回合要打的人是一个区间。然后区间转移即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e6+10;int n,k,m,a[N],f[N],m原创 2021-02-10 18:57:07 · 313 阅读 · 1 评论 -
Poison AND^OR Affection
题目链接:Poison AND^OR Affection对于相同的右端点,我们可以发现当区间的左端点向左移动时,只有log个取值。因为每次要么不变,要么使得一个二进制位由0变成1。对于相同的贡献来说,右端点变大一定不会使得答案变劣,所以我们从最靠右的端点转移即可。如果发现不了,也可以利用区间max转移。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define in原创 2021-01-22 16:20:41 · 199 阅读 · 0 评论 -
Codeforces - Sum of Paths
题目链接:Codeforces - Sum of Paths不难发现,如果能维护每个点在所有路径上面的点数和,那么对于修改不难维护。所以考虑如何维护每个点的出现次数,我们枚举每个点,然后枚举当前点是路径上面第几个点即可。然后就是两种方案数的乘积,就是从任一点到这个点走 x 步的方案数 * 从这个点走 k-x 步出去的方案数。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>原创 2021-01-10 15:21:43 · 203 阅读 · 0 评论 -
Codeforces - Little Elephant and Broken Sorting
题目链接:Codeforces - Little Elephant and Broken Sorting令 dp[i][j] 为 a[i] > a[j] 的概率。然后对于每次交换:交换位置为x,ydp[k][a] = dp[k][b] = ( dp[k][a] + dp[k][b] ) / 2dp[a][k] = dp[b][k] = 1.0 - dp[k][a]转移很显然。最后 dp[a][b] = dp[b][a] = 0.5AC代码:#pragma GCC optimize(原创 2021-01-06 10:58:45 · 143 阅读 · 0 评论 -
Codeforces - Jzzhu and Numbers
题目链接:Codeforces - Jzzhu and Numbers考虑反向枚举每个与运算不为0的集合个数,最后做差。然后我们可以枚举每个最后与起来的答案,我们就可以利用容斥来做。先求出每个集合的超集个数,最后利用二进制中1的个数来容斥。当只有一个1的时候减去这个答案,2个1的时候,由于计算了2次所以加上,然后3个1减去依次类推。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h原创 2021-01-03 20:15:07 · 221 阅读 · 0 评论 -
Codeforces - Bits And Pieces
题目链接:Codeforces - Bits And Pieces我们枚举每个 i ,然后按照二进制高位贪心,如果当前为0才需要管,我们只需要从后面看当前这个需要的二进制集合能否在后面找到二进制与起来,次大的下标。如果满足就加入答案,然后继续看低位。所以我们直接sos dp处理出来每种集合次大的位置。那么与起来也是一定满足的。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>原创 2021-01-03 12:08:35 · 189 阅读 · 0 评论 -
Sum of Log
题目链接:Sum of Log因为 i & j == 0 ,所以考虑 i 或者 j 的最高位即可。然后我们枚举每个当前位为最高位,就需要知道当前位的高位全为 0 ,然后后面合法的方案数。最后统计即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int mod=1原创 2020-12-18 15:36:27 · 606 阅读 · 2 评论 -
Triangle Numbers
题目链接:Triangle Numbers显然一个非0数字出现3次及以上,那么一定合法。否则每个数字出现次数为0,1,2然后状态压缩之后数位dp即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=13;int a[N],pw[N],l,r,dp[N][3&原创 2020-12-09 19:40:22 · 333 阅读 · 0 评论 -
Simple AniPop
题目链接:Simple AniPop不难看出可以区间dp。所以我们考虑后面拼接一段,断环成链。然后我们令 dp[i][j] 为区间 [ i , j ] 并且 i ,j 未被消掉的最大价值。然后枚举区间 [ i +1 , j -1 ]最后消掉的位置k做转移。最后不难看出答案就是 a[i] + dp[i][i+n] 的最大值。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>原创 2020-12-01 13:20:25 · 282 阅读 · 0 评论 -
广告投放
题目链接:广告投放显然有个直接的dp思路,dp[i][j]前 i 个物品,当前还剩人数为 j 的最大值。但是显然无法通过。我们可以发现,对于一个数字每次除以数字向下取整,一共最多 sqrt 种取值,所以预处理出取值,然后按照刚刚的思路 dp 即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace s原创 2020-11-23 20:25:51 · 268 阅读 · 0 评论 -
Codeforces - Clique in the Divisibility Graph
题目链接:Codeforces - Clique in the Divisibility Graph水题,令 dp[i] 为第i个数结尾的答案。显然每个数字只能从因子当中转移。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e6+10;int n,pos[原创 2020-11-19 20:28:25 · 270 阅读 · 0 评论 -
[POI2017]Sabotaż
题目链接:[POI2017]Sabotaż有一个很显然的二分做法,二分之后dp,dp[x]为x的节点当中最多的叛徒个数。然后每次只能从子树当中选一个最大值转移。但是要快读卡常才能过。正解:dp[x] 为x节点未背叛的最小比例,然后考虑从儿子当中转移,有两种情况。当前儿子未背叛:dp[to],当前儿子背叛:算出儿子在所有儿子当中的size比例。显然选最小的转移即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include&原创 2020-11-19 20:01:50 · 249 阅读 · 0 评论 -
置置置换
题目链接:置置置换令 dp[i] 为前 i 个数的排列的方案数。因为是一个排列,所以相对大小都是固定的。1 2 3 的方案数和 1 3 7 的方案数一样。所以我们枚举当前数字 i 加入到前面每个奇数位置 j 当中,从 i - 1 个数字当中选 j -1 个数字,然后再乘数字的方案数。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long lo原创 2020-11-16 11:19:19 · 218 阅读 · 0 评论 -
精简改良
题目链接:精简改良生成树dp。显然最后得到的一定是一颗生成树。我们定义 dp[i][s] 为当前生成树的集合为 s ,根节点为 i 。然后对枚举 s 的子集,让 i 和 子集当中某个点的连边计算贡献。但是无法确定集合之外的点在哪个集合当中,我们再强制子集当中的点不忘外连,显然不会影响答案。所以对当前边的贡献为:g[i][j] * popcount(j) * ( n - popcount(j) )AC代码:#pragma GCC optimize("-Ofast","-funroll-all-原创 2020-11-16 00:25:07 · 151 阅读 · 0 评论 -
Codeforces - Zero Remainder Sum
题目链接:Codeforces - Zero Remainder Sum直接dp[i][j][k][l]表示,前 i 行,第 j 列,选出的数字 %k ,并且第 i 行选了 l 个的最大值。然后考虑状态转移即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=原创 2020-10-21 22:09:16 · 216 阅读 · 0 评论 -
小Z的笔记
题目链接:小Z的笔记显然可以dp,然后 dp[i] 为前 i 个字符的最小删除数量。然后对于每个合法的 j : dp[i] = min{ dp[j] + i - j -1 }显然每次转移越靠后越优,所以我们预处理每个位置前面的最靠后的某个字符位置即可。当然还有一种做法:把 dp[j] - j -1 看成一个整体,单独维护一个min。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.原创 2020-10-06 12:01:56 · 195 阅读 · 0 评论 -
质数取石子
题目链接:质数取石子显然可以枚举素数转移,然后预处理一下素数即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=2e4+10;int n,dp[N],f[N],vis[N];vector<int> p;void init(int n){ f原创 2020-10-05 22:20:49 · 235 阅读 · 1 评论 -
前缀单词
题目链接:前缀单词按照Trie建树,我们可以发现儿子和祖先关系是不能同时选取的。然后树形dp即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=60,M=N*N;int n,ch[M][26],ed[M],idx,dp[M]; char str[N];vec原创 2020-10-04 12:36:38 · 238 阅读 · 1 评论 -
规划
题目链接:规划这个式子显然可以01分数规划,然后问题就变成选n-m个点,并且是一个联通块的最大权值,树形dp即可。dp[i][j] 为以 i 为根节点,选取 j 个点的最大值。然后树上做背包即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=110;int原创 2020-10-04 11:28:04 · 86 阅读 · 0 评论 -
Codeforces - Serval and Rooted Tree
题目链接:Codeforces - Serval and Rooted Tree我们一定是控制最少的可以影响根节点的叶子,然后从大到小放数字。每次取max时,也就是子树中需要控制的最小的。取min的时候也就是求和。然后dp即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;con原创 2020-09-29 13:00:42 · 176 阅读 · 0 评论 -
Codeforces - Shovels Shop
题目链接:Codeforces - Shovels Shop显然最多买k个物品,然后 k^2 dp即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=2e5+10;int dp[N],mx[N],n,m,a[N],k;signed main(){ cin原创 2020-09-28 21:20:08 · 154 阅读 · 0 评论 -
Codeforces - Subsequences
题目链接:Codeforces - Subsequences显然选的越长越优。所以我们对每个长度的子序列求出种类个数即可。求种类个数,直接dp。dp[i][j]为前i个字母,长度为j的方案数。转移的时候如果有前面等于 str[i] 的部分,那么只能从两个相同的字符之间转移。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longus原创 2020-09-26 22:16:11 · 209 阅读 · 0 评论 -
交换茸角
题目链接:交换茸角如果可行。那么对于n个鹿,最多n-1次交换即可。否则,我们一定可以从中选出不相交的子集替换答案。然后枚举子集dp即可。判断是否可行,即sort之后两两是否合法。int i=(s-1)&s;i;i=(i-1)&s 这样即可枚举到s的所有子集,复杂度为 3 ^ nAC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int原创 2020-09-23 20:12:17 · 138 阅读 · 0 评论 -
道路摧毁
题目链接:道路摧毁dp[0/1]分别代表子树中两种点的最小代价。然后树形dp一下即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=2e5+10,M=N*2;int n,mx,my,a[N],dp[N][2];int head[N],nex[M],to[M]原创 2020-09-21 22:50:22 · 203 阅读 · 0 评论 -
WJMZBMR打osu! / Easy
题目链接:WJMZBMR打osu! / Easydp[i] 为以 i 结尾的答案,cnt[i] 为以 i 结尾的连续 o 的期望个数。然后当遇到 ‘?’ 时,考虑两种转移合并即可。然后,这个数组可以滚动优化。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=3原创 2020-09-13 12:53:43 · 346 阅读 · 0 评论 -
Codeforces - Hills
题目链接:Codeforces - Hillsdp[i][j][0/1] 分别代表前 i 个,选 j 个,第 i 个是否选择的最大值。显然选择是不能连续的,因为相邻的是一个偏序关系。所以我们考虑当前第 i 个是否选择,取min即可。如果当前不选的话,从 i-1 是否选择的 min考虑即可。如果当前要选,那么我们从 i-2 是否选择来考虑。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/std原创 2020-09-13 11:50:39 · 208 阅读 · 0 评论 -
Codeforces - Nirvana
题目链接:Codeforces - Nirvana爆搜,或者类似于一个数位dp。枚举当前这一位是否能取到9,然后分是否取9转移。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;int n,a[20],cnt,dp[20][2];int dfs(int pos,int lim){原创 2020-09-12 21:32:01 · 169 阅读 · 0 评论 -
Codeforces - Discrete Centrifugal Jumps
题目链接:Codeforces - Discrete Centrifugal Jumps第一种条件,直接转移即可。对于第二三种,实际上是一样的。我们考虑每个元素对之前元素的影响,我们可以发现这个是一个单调的东西,然后用单调栈维护转移即可。注意:3 1 2 和 3 2 2这种,第二种3是不能转移的。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define in原创 2020-09-09 22:41:25 · 183 阅读 · 0 评论 -
Codeforces - Lucky Country
题目链接:Codeforces - Lucky Country对联通块做背包即可。最坏复杂度是 sqrt(n) * n * logw的,并且logw很小为常数。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e5+10;int n,m,dp[N],cnt[原创 2020-09-03 23:58:10 · 516 阅读 · 0 评论 -
Codeforces - Alternative Thinking
题目链接:Codeforces - Alternative Thinking考虑dpdp[0]为未反转的,dp[1]当前正在反转,dp[2]已经反转完成的最大值。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e5+10;int n,dp[N][3]; c原创 2020-09-03 13:24:30 · 130 阅读 · 0 评论 -
Codeforces - Top Secret Task
题目链接:Codeforces - Top Secret Task考虑dp,dp[i][j][k]为前 i 个数字,取前 j 个数字的最小和,交换 k 次的最小值。然后可以从前面 j-1 的位置转移而来。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=155;i原创 2020-09-03 11:49:40 · 200 阅读 · 0 评论