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考试】的更多相关文章

  1. 两道NOIP里的DP题目~

    拦截导弹    来源:NOIP1999(提高组) 第一题 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都 ...

  2. 与高精死杠的几天——记两道简单的高精dp

    (同样也是noip往年的题 1​.矩阵取数游戏 题目链接[Luogu P1005 矩阵取数游戏] \(\mathcal{SOLUTION}:\) 通过对题目条件的分析,我们可以发现,每一行取数对答案的 ...

  3. leetcode简单题目两道(2)

    Problem Given an integer, write a function to determine if it is a power of three. Follow up: Could ...

  4. 『ACM C++』Virtual Judge | 两道基础题 - The Architect Omar && Malek and Summer Semester

    这几天一直在宿舍跑PY模型,学校的ACM寒假集训我也没去成,来学校的时候已经18号了,突然加进去也就上一天然后排位赛了,没学什么就去打怕是要被虐成渣,今天开学前一天,看到最后有一场大的排位赛,就上去试 ...

  5. 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  6. 两道人数多,课程少,query多的题

    #每天进步一点点# 来两道很相似的题目~ (智商啊智商.....) hihoCoder #1236:Scores (简单的分桶法+bitset) 2015 Beijing Online的最后一题.题目 ...

  7. js 从两道面试题加深理解闭包与箭头函数中的this

     壹 ❀ 引 在本文之前我已经花了两个篇幅专门介绍了JavaScript中的闭包与this,正好今早地铁上看到了两道面试题,试着做了下发现挺有意思,所以想单独写一篇文章来记录解析过程.若你对于闭包与t ...

  8. FJOI2020 的两道组合计数题

    最近细品了 FJOI2020 的两道计数题,感觉抛开数据范围不清还卡常不谈里面的组合计数技巧还是挺不错的.由于这两道题都基于卡特兰数的拓展,所以我们把它们一并研究掉. 首先是 D1T3 ,先给出简要题 ...

  9. ACM/ICPC 之 SPFA范例两道(POJ3268-POJ3259)

    两道以SPFA算法求解的最短路问题,比较水,第二题需要掌握如何判断负权值回路. POJ3268-Silver Cow Party //计算正逆最短路径之和的最大值 //Time:32Ms Memory ...

随机推荐

  1. 树莓派3启动wifi并且配置wifi

    概述 树莓派3内置了wifi和蓝牙模块,我们不用像以前的版本那样,再去购买一个外接的模块练到raspberry上. 当我们第一次启动了树莓派的时候,必然使用了网线,但是之后的每一次使用,我们当然更希望 ...

  2. Flask 扩展 表单

    pip install flask-wtf 一个简单的表单 from flask_wtf import Form from wtforms import StringField from wtform ...

  3. BM V7000数据恢复成功案例;服务器数据恢复

    IBM V7000存储是一款定位中端的存储设备,很多企业选择该服务器作为存储,最近北亚数据恢复中心接到一例V7000服务器数据恢复案例,下面将对本次数据恢复的过程和数据恢复方法进行归纳总结,希望对各位 ...

  4. python使用tesseract-ocr完成验证码识别(模型训练和使用部分)

    一.Tesseract训练 大体流程为:安装jTessBoxEditor -> 获取样本文件 -> Merge样本文件 –> 生成BOX文件 -> 定义字符配置文件 -> ...

  5. python之路--day15---软件开发目录规范

    软件开发目录规范 bin--启动文件 conf--配置文件 core--核心代码 db--数据文件 lib--常用功能代码 log--日志文件 readme--软件介绍

  6. JAVA_SE基础——15.循环嵌套

    嵌套循环是指在一个循环语句的循环体中再定义一个循环语句结构,while,do-while,for循环语句都可以进行嵌套,并且可以互相嵌套,下面来看下for循环中嵌套for循环的例子. 如下: publ ...

  7. Linux知识积累(5) 关机shutdown和重启reboot

    Linux centos关机与重启命令详解与实战 Linux centos重启命令: 1.reboot 2.shutdown -r now 立刻重启(root用户使用) 3.shutdown -r 1 ...

  8. iOS HTML图片本地预览

    引言 相信用过苹果手机的童鞋,会发现很多新闻类的应用,都可以实现HTML图片本地预览,那么这是如何实现的呢?本文将深入阐述其中的原理. 关于此功能,我还实现了一个DEMO,大家可以点击此访问更详细内容 ...

  9. [SHOI2009] 会场预约 - Treap

    Description PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也 ...

  10. python/基础输出输入用法

    输出及输入的简单用法 print print,中文意思是打印,在python里它不是往纸上打印,而是打印在命令行,或者叫终端.控制台里面.print是python里很基本很常见的一个操作,它的操作对象 ...