两道很好的dp题目【4.29考试】
A
问题描述:
对于一个排列,考虑相邻的两个元素,如果后面一个比前面一个大,表示这个位置是上升的,用I表示,反之这个位置是下降的,用D表示。如排列3,1,2,7,4,6,5可以表示为DIIDID。
现在给出一个长度为n-1的排列表示,问有多少种1到n的排列满足这种表示。
输入:
一个字符串S,S由I,D,?组成.?表示这个位置既可以为I,又可以为D。
输出:
有多少种排列满足上述字符串。输出排列数模1000000007
样例输入:
?D
样例输出:
3
数据范围:
20%的数据 S长度<=10
100%的数据 S长度<=1000
分析:怎么做?先想一想,i+1个数的方法数可以用i个数的方法数推出来,自然就想到了dp。一看数据范围,1000,只可以开二维,多半是二维dp。
dp[i][j] i表示共有i个数,j表示当前序列的最后一位为j。可以发现一个东西:前面i个数范围都在1~i且1~i中的每个数都只出现了1次。得出下列结论:
1.'D' 呈下降趋势,当前这位填j,前面那位可以填j+1~i-1(i表示序列长度,已经+1),但这样的话,前面又有一个j,和当前这位j矛盾。我们可以视作前面所有>=j的数全部+1,来避免这种矛盾,所以当前位为j的前一位实际可以填j~i-1。(这一句重点)
2.'I' 呈上升趋势,当前这位填j,前一位填1~j-1的数。为什么不能填j?因为当前位填j后实际上整个序列是少一个为i(i表示序列长度,已经+1)的数的,我们只能把每个>=j的数视作+1来避免这种bug。如果当前位填j,前一位填j,前面那位会被视作+1,矛盾。
3.'?' D和I的情况加起来,耶。
解决。
CODE:
#include<cstdio>
int f[][],mod=;
int main()
{
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
char c;int i=,ans=;
c=getchar();f[][]=;
while(c=='D'||c=='I'||c=='?')
{
i++;
for(int j=;j<i;j++)
f[i-][j]=(f[i-][j]+f[i-][j-])%mod;
if(c=='I'){
for(int j=;j<=i;j++)
f[i][j]=f[i-][j-];
}
if(c=='D'){
for(int j=;j<i;j++)
f[i][j]=(f[i-][i-]-f[i-][j-]+mod)%mod;
}
if(c=='?'){
for(int j=;j<i;j++)
f[i][j]=(f[i-][i-]-f[i-][j-]+mod)%mod;
for(int j=;j<=i;j++)
f[i][j]=(f[i-][j-]+f[i][j])%mod;
}
c=getchar();
}
for(int j=;j<=i;j++)
ans=(ans+f[i][j])%mod;
printf("%d",ans);return ;
}
B
问题描述:
小A非常喜欢字符串,所以小K送给了小A两个字符串作为礼物。两个字符串分别为X,Y。小A非常开心,但在开心之余她还想考考小K。小A定义L为X与Y的最长公共子序列的长度(子序列在字符串内不一定连续,一个长度为L的字符串有2^L个子序列,包括空子序列)。现在小A取出了X的所有长度为L的子序列,并要求小K回答在这些子序列中,有多少个是Y的子序列。因为答案可能很大,所以小K只需要回答最终答案模10^9 + 7。
输入:
第一行包含一个非空字符串X。
第二行包含一个非空字符串Y。
字符串由小写英文字母构成。
输出:
对于每组测试数据输出一个整数,表示对应的答案。
样例输入:
aa
ab
样例输出:
2
数据范围:
对于20%的数据,1 <= |X|,|Y| <= 10
对于100%的数据,1 <= |X|,|Y| <= 1000
分析:一道很有趣的题,我没看出是dp
题目必须读懂,虽说是求a中所有长度为L的序列在b中出现的个数,其实就是求最大长度的lcs有多少种方法。。。cnm坑比题。知道这一点之后,dp方程也就不难想了。
由于范围是1000,所以只能开二维。dp[i][j]定义a中的前i个字符和b中的前j个字符构成的长度为 lcs(i,j)的公共子序列有多少种。
肯定先求lcs,每个位置的lcs都要求。然后dp怎么转移呢?由于是在a中取序列,只考虑a中的某位置的字符取还是不取。
1.如果不取当前这第i位的字符,且lcs[i][j]=lcs[i-1][j],说明啥?说明了a中i位置这个字符对答案并无贡献,所以只用继承就可以。dp[i][j]+=dp[i-1][j]
2.取第i位字符。如果取了这个字符后,会有一个新的lcs长度刚好达到lcs[i][j],那么这个位置的方法数也是可以加过来的。那么我们怎么表示新lcs的结尾在b中对应的是哪个字符(设为x,其最后位置为p)?预处理一下每个字符在b中出现的最后位置。为什么非要p,万一前面的x也可以构成新lcs呢?贪心,后面方法数的肯定比前面的方法数多,取p方法数一定最优。dp[i][j]+=dp[i-1][p-1]
PS:为什么这样做得到的一定是长度为lcs(a,b)的公共子序列,很有意思,lcs(a,b)中存的一定是最长lcs的长度,如果,只有长度满足才会递推过去,啊哈哈哈,啊哈哈哈。
完美解决,耶!
CODE:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define inf 2147483647
#define N 1005
#define mod 1000000007
using namespace std;
int lcs[N][N],dp[N][N],ls[N][];
char a[N],b[N];
void lalala(){
int la=strlen(a+),lb=strlen(b+);
for(int i=;i<=la;i++)
for(int j=;j<=lb;j++){
if(a[i]==b[j])lcs[i][j]=lcs[i-][j-]+;
else lcs[i][j]=max(lcs[i][j-],lcs[i-][j]);
}
} void nanana(){
int lb=strlen(b+);
for(int i=;i<=lb;i++){
memcpy(ls[i],ls[i-],sizeof(ls[i-]));
ls[i][b[i]-'a'+]=i;
}
} int aaa(){
int la=strlen(a+),lb=strlen(b+);
for(int i=;i<=la;i++)dp[i][]=;
for(int j=;j<=lb;j++)dp[][j]=;
for(int i=;i<=la;i++)
for(int j=;j<=lb;j++){
if(lcs[i-][j]==lcs[i][j]){
dp[i][j]+=dp[i-][j];
dp[i][j]%=mod;
}
int p=ls[j][a[i]-'a'+];
if(lcs[i][j]==lcs[i-][p-]+&&p){
dp[i][j]+=dp[i-][p-];
dp[i][j]%=mod;
}
}
return dp[la][lb];
} int main(){
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
scanf("%s",a+);
scanf("%s",b+);
lalala();
nanana();
printf("%d",aaa());
return ;
}
两道很好的dp题目【4.29考试】的更多相关文章
- 两道NOIP里的DP题目~
拦截导弹 来源:NOIP1999(提高组) 第一题 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都 ...
- 与高精死杠的几天——记两道简单的高精dp
(同样也是noip往年的题 1.矩阵取数游戏 题目链接[Luogu P1005 矩阵取数游戏] \(\mathcal{SOLUTION}:\) 通过对题目条件的分析,我们可以发现,每一行取数对答案的 ...
- leetcode简单题目两道(2)
Problem Given an integer, write a function to determine if it is a power of three. Follow up: Could ...
- 『ACM C++』Virtual Judge | 两道基础题 - The Architect Omar && Malek and Summer Semester
这几天一直在宿舍跑PY模型,学校的ACM寒假集训我也没去成,来学校的时候已经18号了,突然加进去也就上一天然后排位赛了,没学什么就去打怕是要被虐成渣,今天开学前一天,看到最后有一场大的排位赛,就上去试 ...
- 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制
你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...
- 两道人数多,课程少,query多的题
#每天进步一点点# 来两道很相似的题目~ (智商啊智商.....) hihoCoder #1236:Scores (简单的分桶法+bitset) 2015 Beijing Online的最后一题.题目 ...
- js 从两道面试题加深理解闭包与箭头函数中的this
壹 ❀ 引 在本文之前我已经花了两个篇幅专门介绍了JavaScript中的闭包与this,正好今早地铁上看到了两道面试题,试着做了下发现挺有意思,所以想单独写一篇文章来记录解析过程.若你对于闭包与t ...
- FJOI2020 的两道组合计数题
最近细品了 FJOI2020 的两道计数题,感觉抛开数据范围不清还卡常不谈里面的组合计数技巧还是挺不错的.由于这两道题都基于卡特兰数的拓展,所以我们把它们一并研究掉. 首先是 D1T3 ,先给出简要题 ...
- ACM/ICPC 之 SPFA范例两道(POJ3268-POJ3259)
两道以SPFA算法求解的最短路问题,比较水,第二题需要掌握如何判断负权值回路. POJ3268-Silver Cow Party //计算正逆最短路径之和的最大值 //Time:32Ms Memory ...
随机推荐
- 用js 获取url 参数 页面跳转 ? 后的参数
记得之前在原来的公司写过这个东西,但是还是忘记怎么接住参数了,只知道怎么把id传过去! 问了身边的大佬 他首先推荐了我一个链接是别人写好的方法 附上链接地址:http://blog.csdn.net/ ...
- 消除ExtJS6的extjs-trila字样
- ExtJs6级联combo的实现
父类获取子类进行操作 { xtype: 'combo', store: Common.Dic.getDicData("IMAGE_BIG_TYPE") , multiSelect: ...
- JAVA_SE基础——9.基本数据类型间的转换
前面我已经教会大家基本的数据类型进行了介绍, 然后这篇文章,我来介绍下,基本数据类型的转换. Java中有两种类型转换形式,分别是自动类型转换和强制类型转换. Step1.自动类型转换. 自动类型 ...
- WIN10系统触摸板快捷键
快捷的手势操作,有时候会让人脱离鼠标,只要不是非用不可的情况,基本上这些常用手势就能让我们摆脱鼠标携带不便或者桌子地方小的烦恼.iOS上的快捷手势很是受欢迎,win10上却鲜有人知晓,尤其是非开发人员 ...
- Python内置函数(58)——input
英文文档: input([prompt]) If the prompt argument is present, it is written to standard output without a ...
- kubernetes入门(03)kubernetes的基本概念
一.Pod 在Kubernetes集群中,Pod是创建.部署和调度的基本单位.一个Pod代表着集群中运行的一个进程,它内部封装了一个或多个应用的容器.在同一个Pod内部,多个容器共享存储.网络IP,以 ...
- SpringBoot应用的属性管理
一.properties 配置文件 1.src/main/application.properties spring.profiles.active=dev spring.application.na ...
- 新概念英语(1-55)The Sawyer family
新概念英语(1-55)The Sawyer family When do the children do their homework? The Sawyers live at 87 King Str ...
- 译《Time, Clocks, and the Ordering of Events in a Distributed System》
Motivation <Time, Clocks, and the Ordering of Events in a Distributed System>大概是在分布式领域被引用的最多的一 ...