tjoi2018D2T2(luogu4590) 游园会 (状压dp)
题解劝退系列
设长的那个串是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)的更多相关文章
- 洛谷P4590 [TJOI2018]游园会(状压dp LCS)
题意 题目链接 Sol 这个题可能是TJOI2018唯一的非模板题了吧.. 考虑LCS的转移方程, \[f[i][j] = max(f[i - 1][j], f[i][j - 1], f[i - 1] ...
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
- nefu1109 游戏争霸赛(状压dp)
题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...
- poj3311 TSP经典状压dp(Traveling Saleman Problem)
题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
- [NOIP2016]愤怒的小鸟 D2 T3 状压DP
[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...
- 【BZOJ2073】[POI2004]PRZ 状压DP
[BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...
- bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)
数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...
- HDU 1074 Doing Homework (状压dp)
题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...
- 【BZOJ1688】[Usaco2005 Open]Disease Manangement 疾病管理 状压DP
[BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) ...
随机推荐
- BZOJ 4804: 欧拉心算
数论题不多BB,直接开始推导吧: \(\sum_{i=1}^n \sum_{j=1}^n \phi(gcd(i,j))\) \(=\sum_{i=1}^n \sum_{j=1}^n \sum_{d=1 ...
- ElasticSearch实践系列(二):探索集群
前言 为了方便ELK的逐步搭建,我们本篇文章先安装Kibana,然后用Kibana的DevTols执行命令.也可以安装elasticsearch-head运行命令. 安装Kibana 参考Instal ...
- Python从菜鸟到高手(3):声明变量
变量(variable)是Python语言中一个非常重要的概念.变量的主要作用就是为Python程序中的某个值起一个名字.类似于"张三"."李四"." ...
- openssl版本升级操作记录
需要部署nginx的https环境,之前是yum安装的openssl,版本比较低,如下: [root@nginx ~]# yum install -y pcre pcre-devel openssl ...
- Linux下的计算命令和求和、求平均值、求最值命令梳理
在Linux系统下,经常会有一些计算需求,那么下面就简单梳理下几个常用到的计算命令 (1)bc命令bc命令是一种支持任意精度的交互执行的计算器语言.bash内置了对整数四则运算的支持,但是并不支持浮点 ...
- ZooKeeper 典型的应用场景——及编程实现
如何使用 Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但是 Zookeeper 并不是用来专门存储 ...
- Visual Studio2013的安装过程及练习测试
一.安装环境: 支持安装的操作系统版本:Windows XP,Windows7,Windows8,Windows10. CPU大小:Intel(R)Core(TM)i5-4210U CPU @1.7G ...
- Individual Project-word frequency
预计时间: 项目要求理解:半小时 c#语言了解:6小时 构思程序框架:2小时 编写调试程序:4小时 项目实际完成时间: 项目要求理解:半小时 c#语言了解:6小时 构思程序框架:2小时 编写调试程序: ...
- #个人作业Week2——结对编程对象代码复审
General 代码能够正确运行,能够正确生成指定数量的题目和答案,并且能够对给出的题目和答案文件进行比对,输出结果. 代码没有非常复杂的逻辑,比较容易理解,但是在缺少注释的情况下有部分代码需要较长时 ...
- 定义类型别名(typedef,using)
说到类型别名,无非是给类型名(如int,char,float,double,bool)取一个比较有特殊含义的名字而已 最常用的关键莫过于 typedef 吧 typedef最常见的用法是与结构体str ...