DP套DP,就是将内层DP的结果作为外层DP的状态进行DP的方法。

[BZOJ3864]Hero meet devil

对做LCS的DP数组差分后状压,预处理出转移数组,然后直接转移即可。

tr[S][k]表示当前差分状压后的状态为S,加入字符k(k为ACGT中一个)后会转移到什么状态。

f[i][S]表示串已构造到第i位,和模式串的匹配状态差分后为S,的方案数。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  5. typedef long long ll;
  6. using namespace std;
  7.  
  8. const int N=,M=,mod=1e9+;
  9. int T,n,m,d[],g[],ans[N],tr[M][],cnt[M],f[][M];
  10. char s[],c[]="ACGT";
  11.  
  12. int main(){
  13. freopen("bzoj3864.in","r",stdin);
  14. freopen("bzoj3864.out","w",stdout);
  15. for (scanf("%d",&T); T--; ){
  16. scanf("%s%d",s+,&m); n=strlen(s+);
  17. for (int S=; S<<<n; S++){
  18. if (S) cnt[S]=cnt[S^(S&-S)]+;
  19. rep(i,,n-) d[i+]=d[i]+((S>>i)&);
  20. rep(k,,){
  21. rep(i,,n) g[i]=max(max(d[i],g[i-]),(c[k]==s[i])?d[i-]+:);
  22. tr[S][k]=;
  23. rep(i,,n-) if (g[i+]-g[i]) tr[S][k]|=<<i;
  24. }
  25. }
  26. memset(ans,,sizeof(ans)); memset(f,,sizeof(f)); f[][]=;
  27. rep(i,,m){
  28. int v=i&,u=v^; memset(f[v],,sizeof(f[v]));
  29. for (int S=; S<<<n; S++)
  30. rep(k,,) f[v][tr[S][k]]=(f[v][tr[S][k]]+f[u][S])%mod;
  31. }
  32. for (int S=; S<<<n; S++) ans[cnt[S]]=(ans[cnt[S]]+f[m&][S])%mod;
  33. rep(i,,n) printf("%d\n",ans[i]);
  34. }
  35. return ;
  36. }

[BZOJ5336][TJOI2018]party

同上题,多加一维0/1/2表示末尾和'NOI'匹配到第几位即可。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  5. typedef long long ll;
  6. using namespace std;
  7.  
  8. const int N=,M=,mod=1e9+;
  9. int T,n,m,d[],g[],ans[N],tr[M][],cnt[M],f[][M][];
  10. char s[],c[]="NOI";
  11.  
  12. int main(){
  13. freopen("bzoj5336.in","r",stdin);
  14. freopen("bzoj5336.out","w",stdout);
  15. scanf("%d%d%s",&m,&n,s+);
  16. for (int S=; S<<<n; S++){
  17. if (S) cnt[S]=cnt[S^(S&-S)]+;
  18. rep(i,,n-) d[i+]=d[i]+((S>>i)&);
  19. rep(k,,){
  20. rep(i,,n) g[i]=max(max(d[i],g[i-]),(c[k]==s[i])?d[i-]+:);
  21. tr[S][k]=;
  22. rep(i,,n-) if (g[i+]-g[i]) tr[S][k]|=<<i;
  23. }
  24. }
  25. f[][][]=;
  26. rep(i,,m){
  27. int v=i&,u=v^; memset(f[v],,sizeof(f[v]));
  28. for (int S=; S<<<n; S++) rep(l,,) if (f[u][S][l]){
  29. rep(k,,){
  30. int S1=tr[S][k],l1=l;
  31. l1=(k==l) ? l1+ : ((!k)?:);
  32. if (l1<) f[v][S1][l1]=(f[v][S1][l1]+f[u][S][l])%mod;
  33. }
  34. }
  35. }
  36. for (int S=; S<<<n; S++)
  37. rep(i,,) ans[cnt[S]]=(ans[cnt[S]]+f[m&][S][i])%mod;
  38. rep(i,,n) printf("%d\n",ans[i]);
  39. return ;
  40. }

[BZOJ3591]最长上升子序列

给出1~n的一个排列的一个最长上升子序列,求原排列可能的种类数。

考虑最长上升子序列$O(n\log n)$算法中使用的单调队列,将单调队列中的数组成的集合作为状态DP。

f[S]表示当前状态S的方案数,其中S是一个三进制数,第i位为0表示这个数尚未被选入数列,1表示选入数列但不在单调队列中,2表示在单调队列中。

对于每个状态,枚举下一个加入序列的数是什么来转移。可以先预处理减小常数。

具体细节可看代码注释,$O(2^n n^2+3^n n)$

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define rep(i,l,r) for (int i=(l); i<=(r); i++)
  5. using namespace std;
  6.  
  7. const int N=,M=1.5e7;
  8. int n,m,x,id[N],p[N],f[M];
  9. bool flag[<<N][N];
  10. int v[<<N][N],c[<<N],mx[<<N],s[<<N],ans=;
  11.  
  12. int main(){
  13. freopen("bzoj3591.in","r",stdin);
  14. freopen("bzoj3591.out","w",stdout);
  15. scanf("%d%d",&n,&m);
  16. rep(i,,m) scanf("%d",&x),id[x-]=i;
  17. p[]=; rep(i,,n) p[i]=p[i-]*;
  18. for (int S=; S<(<<n); S++)//预处理出每个可能的状态转移,S为当前已经选进单调队列的集合,flag表示能否转移,v是转移到什么位置
  19. rep(i,,n-){
  20. if (S&(<<i)){ c[S]+=p[i]; mx[S]=max(mx[S],i); s[S]++; continue; }
  21. //c:全1的三进制状态,mx:最大数,s:popcount
  22. if (!id[i]) flag[S][i]=;
  23. else{
  24. int tot=;
  25. rep(j,,n-) if (S&(<<j) && id[j]) tot++;
  26. if (tot+==id[i]) flag[S][i]=;//满足在LIS中的位置为id[i]
  27. }
  28. int t=-,x=;
  29. rep(j,,n-) if (S&(<<j)) x+=p[j];//S转三进制
  30. for (int j=n-; j>i; j--) if (S&(<<j)) t=j;//找到集合中比i大的最小的数更新
  31. if (~t) v[S][i]=x-p[t]+p[i]; else v[S][i]=x+p[i];
  32. }
  33. f[]=;
  34. for (int x=; x<(<<n); x++)
  35. for (int y=x; y> || (!y && !x); (!x) ? y-- : y=(y-)&x)//x为已在序列中的数的集合,y为在单调队列中数的集合
  36. if (f[c[x]+c[y]]){
  37. int t=c[x]+c[y];
  38. for (int i=; s[y]==m ? i<mx[y] : i<n; i++)//枚举新加进序列的数(若单调队列长度已满则不能加入更大的数)
  39. if (flag[x][i]) f[c[x]+p[i]+v[y][i]]+=f[t];//新加进序列的数一定也加进单调队列
  40. if (x==(<<n)-) ans+=f[t];
  41. }
  42. printf("%d\n",ans);
  43. return ;
  44. }

DP套DP的更多相关文章

  1. bzoj 3864: Hero meet devil [dp套dp]

    3864: Hero meet devil 题意: 给你一个只由AGCT组成的字符串S (|S| ≤ 15),对于每个0 ≤ .. ≤ |S|,问 有多少个只由AGCT组成的长度为m(1 ≤ m ≤ ...

  2. [模板] dp套dp && bzoj5336: [TJOI2018]party

    Description Problem 5336. -- [TJOI2018]party Solution 神奇的dp套dp... 考虑lcs的转移方程: \[ lcs[i][j]=\begin{ca ...

  3. luogu 4158 粉刷匠 dp套dp

    dp套dp 每个木板是个递推的dp,外部是个分组背包 #include<bits/stdc++.h> #define rep(i,x,y) for(register int i=x;i&l ...

  4. Codeforces 372B Counting Rectangles is Fun:dp套dp

    题目链接:http://codeforces.com/problemset/problem/372/B 题意: 给你一个n*m的01矩阵(1 <= n,m <= 40). 然后有t组询问( ...

  5. 【BZOJ3864】Hero meet devil DP套DP

    [BZOJ3864]Hero meet devil Description There is an old country and the king fell in love with a devil ...

  6. codeforces 979E(dp套dp)

    题意: 有n个点,编号为1~n.有的点颜色是黑色,有的点颜色是白色,有的点的颜色待涂.你还可以连一些边,但这些边一定是从小编号连到大编号的点. 对于一个确定的图,我们去统计有多少条路径满足“该路径经过 ...

  7. dp 套 dp扯谈

    1.[扯谈概念] \(dp\) 套 \(dp\) 其实也就是 \(dp\) . 这里就定义下面两个概念: 内层 \(dp\) 表示的是被套在里面的那个 \(dp\) 外层 \(dp\) 表示的是最外面 ...

  8. P4590-[TJOI2018]游园会【dp套dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P4590 题目大意 给出一个长度为\(m\)的字符串\(s\). 对于每个\(k\in[0,m]\)求有多少个长度为 ...

  9. 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)

    洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\)​​​​​.我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...

随机推荐

  1. JS练习题(左侧菜单下拉+好友选中)

    题一.左侧菜单下拉 做题思路:先做菜单和子菜单,把子菜单默认隐藏.再用JS调样式. <style type="text/css"> *{ margin:0px auto ...

  2. quick-cocos2dx lua中读取 加密 csv表

    我非常想把一些非必需的信息以CSV表的格式保存到客户端,以减少和服务器的通讯,降低压力.于是写了这么一个. 但因为大家觉得这样的话,需要每次登陆时来检测同步这些数据,会减慢登陆速度,于是没有用到. 我 ...

  3. hdu 1395 2^x mod n = 1(暴力题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1395 2^x mod n = 1 Time Limit: 2000/1000 MS (Java/Oth ...

  4. TensorFlow两种方式计算Cross Entropy

    sparse_softmax_cross_entropy_with_logits与softmax_cross_entropy_with_logits import tensorflow as tf y ...

  5. 史诗级Java/JavaWeb学习资源免费分享

    黑马内部视频+相关配套学习资料 Java Spring 技术栈构建前后台团购网站 Java SSM开发大众点评后端 欢迎关注微信公众号:Java面试通关手册 回复关键词: "资源分享第一波& ...

  6. MFC单文档框架分析及执行流程(转)

    原文转自 https://blog.csdn.net/u011619422/article/details/40402705 首先来分析一下MFC单文档类的结构: 它包括如下几个类: CAboutDl ...

  7. Pythone3 sys模块

    1.sys.argv 可以实现从程序外部向程序传递参数2.sys.exit() 程序中间退出,exit(0)正常退出,其他为异常退出3.sys.getdefaultencoding() 获取系统编码方 ...

  8. Aspxgridview 根据条件来自定义计算Totalsummery

    protected void ASPxGridView1_CustomSummaryCalculate(object sender, DevExpress.Data.CustomSummaryEven ...

  9. [bugfix]copy属性参数将NSMutableArray变为NSArray类型

    问题:NSMutableArray 声明为 copy 属性参数后即使接受NSMutableArray变量依然为NSArray变量 测试: 属性申明为: 1 @property (nonatomic, ...

  10. Memcached内存缓存技术

    Memcached是什么,有什么作用? Memcached是一个开源的.高性能的内存缓存软件,从名称上看Mem就是内存的意思,而Cache就是缓存的意思. Memcached通过在事先规划好的内存空间 ...