BZOJ5336 TJOI2018 party


Description

小豆参加了NOI的游园会,会场上每完成一个项目就会获得一个奖章,奖章 只会是N, O, I的字样。在会场上他收集到了K个奖章组成的串。

兑奖规则是奖章串和兑奖串的最长公共子序列长度为小豆最后奖励的等级。

现在已知兑奖串长度为N,并且在兑奖串上不会出现连续三个奖章为NOI,即奖章中不会出现子串NOI。

现在小豆想知道各个奖励等级会对应多少个不同的合法兑奖串。

Input

第一行两个数,N,K分别代表兑奖串的长度,小豆收集的奖章串的长度。

第二行一共K个字符,表示小豆得到奖章串。

N<=1000 & K<=15

Output

一共K+1行,第i行表示小豆最后奖励等级为i-1的不同的合法兑奖串的个数,可能这个数会很大,结果对10^9 + 7取模。

Sample Input

3 2

NO

Sample Output

1

19

6

提示

最长公共子序列长度0的串有:III;

最长公共子序列长度2的串有:NON, NNO, NOO, ONO,INO, NIO;

除去NOI,余下的19(26-6-1)种为最长公共子序列长度为1。


我们发先在对lsm进行计算的时候相邻两个DP值的差最多是一,所以我们借此进行状态构造。把一个dp值差分后的01串作为状态,然后对这个状态进行DP,因为我们需要考虑的特殊情况只有NOI,所以添加一维记一下状态就好了


#include<bits/stdc++.h>
using namespace std;
#define K 20
#define N 1010
#define S (1<<16)
#define Mod 1000000007
int n,k,bit[K],ans[K]={0};
int now[K]={0},res[K]={0},a[K];
int T[S][3]={0};
int dp[2][3][S]={0},ind=0,frm=1;
/*
dp数组中第二维
0->没有特殊限制
1->末尾是N
2->末尾是NO
*/
/*
N->0
O->1
I->2
*/
void add(int &x,int y){x=(x+y)%Mod;}
int countsiz(int s){int cnt=0;while(s)cnt++,s-=s&-s;return cnt;}
int main(){
scanf("%d%d",&n,&k);
getchar();
for(int i=1;i<=k;i++){
char c;scanf("%c",&c);
if(c=='N')a[i]=0;
if(c=='O')a[i]=1;
if(c=='I')a[i]=2;
}
bit[1]=1;for(int i=2;i<=k;i++)bit[i]=bit[i-1]<<1;
int up=(1<<k)-1;
for(int s=0;s<=up;s++){
for(int i=1;i<=k;i++)
now[i]=now[i-1]+(bool)(s&bit[i]);
for(int typ=0;typ<3;typ++){
for(int i=1;i<=k;i++)
if(a[i]==typ)res[i]=now[i-1]+1;
else res[i]=max(res[i-1],now[i]);
for(int i=1;i<=k;i++)T[s][typ]|=bit[i]*(res[i]-res[i-1]);
}
}
dp[ind][0][0]=1;
for(int i=1;i<=n;i++){
ind^=1;frm^=1;
memset(dp[ind],0,sizeof(dp[ind]));
for(int s=0;s<=up;s++){
//没有限制->没有限制(当前出现O或I)
add(dp[ind][0][T[s][1]],dp[frm][0][s]);
add(dp[ind][0][T[s][2]],dp[frm][0][s]);
//没有限制->限制1(当前出现N)
add(dp[ind][1][T[s][0]],dp[frm][0][s]);
//限制1->没有限制(当前出现I)
add(dp[ind][0][T[s][2]],dp[frm][1][s]);
//限制1->限制1(当前出现N)
add(dp[ind][1][T[s][0]],dp[frm][1][s]);
//限制1->限制2(当前出现O)
add(dp[ind][2][T[s][1]],dp[frm][1][s]);
//限制2->没有限制(当前出现O)
add(dp[ind][0][T[s][1]],dp[frm][2][s]);
//限制2->限制1(当前出现N)
add(dp[ind][1][T[s][0]],dp[frm][2][s]);
}
}
for(int s=0;s<=up;s++)
for(int i=0;i<3;i++)
add(ans[countsiz(s)],dp[ind][i][s]);
for(int i=0;i<=k;i++)printf("%d\n",ans[i]);
return 0;
}


BZOJ5336 TJOI2018 party 【状压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) ...

  10. 【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP

    [BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排 Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M< ...

随机推荐

  1. RSA非对称加密算法

    基本定义: RSA公开密钥密码体制.所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制.在公开密钥密码体制中,加密密钥(即公开密钥 ...

  2. 通过spring整合activeMQ实现jms实例

    写的很详细 http://blog.csdn.net/leonardo9029/article/details/43154385

  3. PHP数组合并:[“+”运算符]、[array_merge]、[array_merge_recursive]区别

    1.“+”运算符规则: 当两个数组的键名是数字键名或者字符串键名 $c = $a + $b 在$a后追加($b在$a中不存在的键名)键名和值注意: 1.不覆盖,只是追加不存在的键名和对应的值 2.键名 ...

  4. mysql数据库建表

    主键的问题: 简单的id递加.不过在实习的时候,因为id递增的问题,导致一个项目最后好像产生了严重的问题.所以递增适合小型项目,对我们的项目来说90%足够可以用的. 一些限制: 一般就非空就行,唯一的 ...

  5. ItemsControl控件-----常用的

    常用的ItemsControl控件有:ListBox.ComboBox.TreeView.DataGrid等等.(小结:均是“多项”控件,多项 对应 集合,单项 对应 元素) ItemsControl ...

  6. vim 删除多列

    比如想删除一个文件的1-1000行的前3列: gg #到文件首ctrl+v #可视块模式999j,2l #注意是小写的J和L(方向键向下和向右也可以)d #删除

  7. SSM配置Socket多线程编程(RFID签到实例)

    1.SocketServiceLoader.java package cn.xydata.pharmacy.api.app.test; import javax.servlet.ServletCont ...

  8. 启用/禁用以太网的批处理,用于一个网卡切换本地网络和wifi使用(Win10)

    注意下面时英文版上默认网络使用,同时接入了网线和wifi时,本地网络优先wifi. 所以禁用本地网络就会自动连接到wifi,启用本地网络,就会禁用wifi. 批处理支持 -y 参数,跳过用户输入y,代 ...

  9. ubuntu14.04 改变系统默认Python解释器

    今天刚安装了anaconda,摸索了一阵子,现做个相关记录. 虽然安装的时候,会通知你是否加入环境变量(加到.bashrc尾部),但是调用的解释器仍然是系统自带默认的Python2.7.6,我们在/r ...

  10. Linux用root强制踢掉已登录用户;用fail2ban阻止ssh暴力破解root密码

    Linux用root强制踢掉已登录用户   首先使用w命令查看所有在线用户: [root@VM_152_184_centos /]# w 20:50:14 up 9 days, 5:58, 3 use ...