题解劝退系列

设长的那个串是A,短的那个串是B。

那我们在如果已经知道某个A的时候,A[1..i]和B[1..j]的最长公共子序列$f[i][j]=max\{f[i-1][j],f[i][j-1],f[i-1][j-1]+(A[i]==B[i])\}$

于是可以递推来枚举A,顺手把NOI的情况判掉。但这复杂度显然过不了。

注意到在推的时候,每新加一个字符,就可以由f[i-1]推出f[i],也就是说,我们根本不用记递推出来的这个A具体是什么,只要记住这个f[i]就可以了。

怎么记呢?注意到f[i][j]只能等于f[i][j-1]或者f[i][j-1]+1,也就是说,我们可以先差分这个f[i],然后状压就能记下来了。

设trans[s][k]表示原本f数组状态是s、新加了一个k字符,转移到的状态

那么可以得到递推式$g[i+1][trans[s][k]]=\sum{g[i][s]}$,g[N][s]就是最后状态s的情况数,只要统计一下s中1的个数,记到答案里就行了。

然而还要判NOI

其实很简单,只要给g多记一维,用来表示现在这个状态已经匹配到了NOI的几位就可以了

(0,1,2通过"N"转移到1;1通过“O”转移到2;2通过“I”转移到3(这个情况不合法))

要开滚动数组

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<ctime>
#include<set>
#define pa pair<int,int>
#define lowb(x) ((x)&(-(x)))
#define REP(i,n0,n) for(i=n0;i<=n;i++)
#define PER(i,n0,n) for(i=n;i>=n0;i--)
#define MAX(a,b) ((a>b)?a:b)
#define MIN(a,b) ((a<b)?a:b)
#define CLR(a,x) memset(a,x,sizeof(a))
#define rei register int
using namespace std;
const int maxn=,maxk=,maxs=,p=1e9+;
typedef long long ll; ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,K,M;
int wd[maxk],ans[maxk],ne[][];
int f[][maxs][],trans[maxs][],cnt[maxs]; inline void modadd(int &x,int y){x=(x+y)%p;} int main(){
//freopen(".in","r",stdin);
rei i,j,k,l;
N=rd(),K=rd();M=<<K;
i=;while(i<K){
char c=getchar();
if(c=='N') wd[++i]=;
else if(c=='O') wd[++i]=;
else if(c=='I') wd[++i]=;
}
REP(i,,M-){
REP(j,,){
int s=,sum=,lst=,now=;
REP(k,,K){
if(wd[k]==j) now=sum+;
if(i&(<<(k-))) sum++;
if(wd[k]!=j) now=sum;
s+=(now>lst)<<(k-);lst=MAX(lst,now);
}trans[i][j]=s;cnt[i]=sum;
//printf("%d %d %d %d\n",i,j,s,sum);
}
}
ne[][]=;ne[][]=ne[][]=ne[][]=;
bool b=;f[][][]=;
REP(i,,N-){
//memcpy(f[b],f[b^1],sizeof(f[b]));
CLR(f[b^],);
REP(j,,M-){
REP(l,,){if(!f[b][j][l]) continue;
REP(k,,){
if(l==&&k==) continue;
modadd(f[b^][trans[j][k]][ne[l][k]],f[b][j][l]);
//printf("f[%d][%d][%d]=%d -%d> ",i,j,l,f[b][j][l],k);
// printf("f[%d][%d][%d]=%d\n",i+1,trans[j][k],ne[l][k],f[b^1][trans[j][k]][ne[l][k]]);
}
}
}b^=;
}
REP(i,,M-){
REP(j,,)
modadd(ans[cnt[i]],f[b][i][j]);
}REP(i,,K) printf("%d\n",ans[i]);
return ;
}

tjoi2018D2T2(luogu4590) 游园会 (状压dp)的更多相关文章

  1. 洛谷P4590 [TJOI2018]游园会(状压dp LCS)

    题意 题目链接 Sol 这个题可能是TJOI2018唯一的非模板题了吧.. 考虑LCS的转移方程, \[f[i][j] = max(f[i - 1][j], f[i][j - 1], f[i - 1] ...

  2. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  3. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  4. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  5. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  6. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

  7. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

  8. HDU 1074 Doing Homework (状压dp)

    题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...

  9. 【BZOJ1688】[Usaco2005 Open]Disease Manangement 疾病管理 状压DP

    [BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) ...

随机推荐

  1. 蓝牙 link timeout分析

    蓝牙主机和蓝牙设备建立连接之后,会在l2cap 层面上建立相应的channel,这些channel 基本上是用于各种不同的profile 或者protocol 进行通信用的. 当相应的profile或 ...

  2. 记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)

    0x01 前言 最近在做代码审计的工作中遇到了一个难题,题目描述如下: <?php include 'flag.php'; if(isset($_GET['code'])){ $code = $ ...

  3. Python_复习_习题_29

    # 之前做得的题 以后再遇到能保证会# 下周二考 :所有的知识# 面试题:认真对待## 三元运算符# 接收结果的变量 = 条件为真的结果 if 条件 else 条件为假的结果# 接收结果的变量 = “ ...

  4. ecna2017-Game of Throwns

    这题就是给你一个标号为0-n-1的环,然后给你M个操作,操作有两种,一种是直接给一个数,这数的正负代表我当前向前(向后)仍了xx个位置的球,或者给你一个撤销操作表示为 undo m,表示撤销最近的M个 ...

  5. Adobe Photoshop CC 2015使用及扩展工具

    VAdobe Photoshop CC 2015: 简称"PS",是由Adobe Systems开发和发行的图像处理软件 扩展工具: Cuuterman:切图插件: 一个一个切图, ...

  6. 20145221 《Java程序设计》实验报告四:Android开发基础

    20145221 <Java程序设计>实验报告四:Android开发基础 实验要求 基于Android Studio开发简单的Android应用并部署测试; 了解Android组件.布局管 ...

  7. Linux环境C程序设计

    Linux基础 常用shell命令 命令 说明 命令 说明 man 查看联机帮助 ls 查看目录及文件列表 cp 复制目录或文件 mv 移动目录或文件 cd 改变文件或目录 rm 删除文件或目录 mk ...

  8. HanderBar

    对于java开发,涉及到页面展示时,比较主流的有两种解决方案: 1. struts2+vo+el表达式. 这种方式,重点不在于struts2,而是vo和el表达式,其基本思想是:根据页面需要的信息,构 ...

  9. 广商博客冲刺第三天new

    第二天沖刺傳送門 第三四天沖刺傳送門 这一天我们主要是弄网页前台设计跟框架设计,这方面主要是由张奇聪负责.我们在amaze ui,smart ui,angularjs+bootstrap中挑选,最终选 ...

  10. zookeeper安装Linux

    安装环境: Linux:centos6.4 Jdk:1.7以上版本 Zookeeper是java开发的可以运行在windows.linux环境.需要先安装jdk. 安装步骤: 第一步:安装jdk 第二 ...