题目链接
题目大意就是给一个长的字符串a和一个短的字符串b,询问a里面有多少个序列是大于b的。

这里我们分两步来处理,就是我们先算出a中的序列长度和b一样的。因为显然答案是由序列长度一样的数量+序列长度>b的数量。为什么不能直接一起算,因为dp的限制(下面讲)?

(1)计算序列长度一样的数量。我们这么考虑由于序列长度是一样的,我们就可以枚举位数的时候有一个比较值。我们类比一下数位dp,数位dp是只要我的高位比限制的范围小,那么地位就可以0-9随便取。转到到我们这道题就是,
我们要最终序列比b大,那么就是我在高位只要有某一位比b的对应位大,那么我下面是随便取都可以满足要求。
我们就这么去设计f[i][j][0/1],i表示现在枚举到b串的第几位,j表示现在枚举到a串的第几位,如果新序列第i位为a[j]那么合法序列是多少个。0表示这个序列正好和b序列一样,1表示高位的某一位已经大于b了所以后面瞎取都可以
这里对于方程的转移就要分三种情况

  1. a[j] < b[i]; 如果a中第j的数字是小于b中的i的数字,那么很明显,我们如果要出现一个大于b的有效序列那么只能是之前的高位已经有大于b所对应数字。即: f[i][j][1] = sum(f[i-1][k][1],(0=<k<= j-1)).,这里无法转移出f[i][j][0]因为你在这一位已经比b小了,不可能出现一样的序列了。
  2. a[j] == b[i] 那么我们要出现合法序列就是前方的序列不管是大于b还是正好等于b都一起加上,对于f[i][j][0] = sum(f[i-1][k][0],(0=<k<= j-1)).,这个式子不能加上f[i-1][k][1]因为你前面大于标准序列了,那么你后面不可能出现与标准序列一样的序列。但是,这个情况我们还可以推出f[i][j][1],因为只要选取前面的序列大于标准序列的就好了,方程和1的方程同理。
  3. a[j] > b[i] 好这一位的值比标准序列的那一位大,那么说明什么?我们之前出现的刚好等于的,和以及超过的都可以算加上去,也就是f[i][j][1] = sum(f[i-1][k][0]+f[i-1][k][1])(0=<k<= j-1),因为我们这一位是比标准的序列大的,所以可以吧前面不管是正好等于的,还是超过的都加上。
    这就是答案的一部分,很明显上面的sum是可以利用前缀和数组去O(1)算出来的,看到这里你知道为什么这种方程不能转移出序列长度大于标准序列的情况了吗,因为比标准序列高位的状态我们无法表示,存标准序列是[1,m]但是我们要表示高位向地位也是[1,k],如果用1表示最高位,就于存入数据的b[1]矛盾。因为我们本来是原本没有存在的最高位只能是0.

我们来考虑另一部分,我们怎么算长度大于标准序列的数目?这里由于我菜 没去想到组合数的方法。我用了第二个dp。
用dp[i][j]表示i个数选了j个的方案数。但是当j等于1的时候如果i所代表的数字是0那么则不能+1,反之就可以+1,这个dp就蛮简单的了。
dp[i][j] += dp[i-1][j];//这个数字我选了
dp[i][j] += dp[i-1][j-1];//这个数字不选
稍稍特判j等于1的情况就好了
dp[i][1] = dp[i - 1][1];如果a[i] != '0’则dp[i][1]++;

最后!两个答案一加就是了!

#include<iostream>
#include<cstdio>
#include<stack>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<time.h>
#include<string>
#include<cmath>
#include <ctime>
#include<bitset>
#include <cctype>
#define debug cout<<"*********degug**********"<<endl;
#define ll long long
#define yn yn_
#define RE register
using namespace std;
const long long max_ = 3000 + 10;
const int mod = 998244353;
const int inf = 1e9;
const long long INF = 1e18;
int read() {int s = 0, f = 1;char ch = getchar();while (ch<'0' || ch>'9') {if (ch == '-')f = -1;ch = getchar();}while (ch >= '0'&&ch <= '9') {s = s * 10 + ch - '0';ch = getchar();}return s * f;
}
int max(int a, int b) {return a > b ? a : b;
}
int min(int a, int b) {return a < b ? a : b;
}
int T, n, m, f[max_][max_][3], sum0[max_][max_], sum1[max_][max_], g[max_][max_];
char nan_[max_], bei[max_];
signed main() {cin >> T;while (T--) {cin >> n >> m;scanf("%s", nan_ + 1);scanf("%s", bei + 1);//cin >> (nan_ + 1);//cin >> (bei + 1);//找nan_的子序列比bei大的数量f[0][0][0] = 1; sum0[0][0] = 1;for (int j = 1; j <= n; j++) {sum0[0][j] += sum0[0][j - 1];}for (int i = 1; i <= m; i++) {//现在是bei的第i位for (int j = 1; j <= n; j++) {if (nan_[j] - '0' < bei[i] - '0') {f[i][j][1] += (sum1[i - 1][j - 1] % mod); f[i][j][1] %= mod;}elseif (nan_[j] - '0' == bei[i] - '0') {f[i][j][0] += sum0[i - 1][j - 1]; f[i][j][0] %= mod;f[i][j][1] += sum1[i - 1][j - 1]; f[i][j][1] %= mod;}else {f[i][j][1] += ((sum0[i - 1][j - 1] % mod) + (sum1[i - 1][j - 1] % mod)) % mod; f[i][j][1] %= mod;}sum0[i][j] += sum0[i][j - 1] + f[i][j][0]; sum0[i][j] %= mod;sum1[i][j] += sum1[i][j - 1] + f[i][j][1]; sum1[i][j] %= mod;}}int ans = 0;ans += sum1[m][n];ans %= mod;for (int i = 1; i <= n; i++) {g[i][1] = g[i - 1][1]; g[i][1] %= mod;if (nan_[i] - '0' != 0)g[i][1]++;for (int j = 2; j <= i; j++) {g[i][j] = g[i - 1][j];g[i][j] %= mod;g[i][j] += g[i - 1][j - 1];g[i][j] %= mod;}}for (int j = m + 1; j <= n; j++) {ans += g[n][j];ans %= mod;}cout << ans << "\n";int tt = max(n, m) + 1;for (int i = 0; i <= tt; i++) {for (int j = 0; j <= tt; j++) {f[i][j][0] = f[i][j][1] = sum0[i][j] = sum1[i][j] = g[i][j] = 0;}}}return 0;
}

详解吉首大学第九届“新星杯”G芒砀山的神秘数字 两种dp相关推荐

  1. Kafka详解(上)——消息系统分类、Kafka安装、两种启动、基本概念、两种架构、核心配置文件

    1 消息和消息系统 ​ 消息(Message)是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象. 1-1 消息系统是什么 ​ 消息系统负责将数据从一个应用 ...

  2. ajax加载vue数据,详解使用Vue.Js结合Jquery Ajax加载数据的两种方式

    整理文档,搜刮出一个使用vue.js结合jquery ajax加载数据的两种方式的代码,稍微整理精简一下做下分享. 废话不多说,直接上代码 html代码 demo {{message }} 测试jqu ...

  3. 2018第九届蓝桥杯JavaB组省赛真题及详解

    2018第九届蓝桥杯JavaB组省赛真题及详解 第一题:第几天 第二题:方格计数 第三题:复数幂 第四题:测试次数 第五题:快速排序 第六题:递增三元组 第七题:螺旋折线 第八题:日志统计 第九题:全 ...

  4. 吉首大学第七届“新星杯”程序设计大赛---补题概况

    吉首大学第七届"新星杯"程序设计大赛---补题http://120.78.162.102/contest.php?cid=1332 先来发图片...(唉...AC九道,就A不动了, ...

  5. 【训练题27:单调队列实现RMQ(附带详细说明)】 H :圣诞糖果 | 吉首大学第十届“新星杯”

    H :圣诞糖果 | 吉首大学第十届"新星杯" 题外话 差一题就能拿一等奖了,有点残念 当时试过了线段树/树状数组/优先队列写法,但是都没过 这题网上我没找到题解,估计也只能用单调队 ...

  6. 阶乘末尾蓝桥杯java_Java实现第九届蓝桥杯阶乘位数

    阶乘位数 题目描述 小明维护着一个程序员论坛.现在他收集了一份"点赞"日志,日志共有N行.其中每一行的格式是: ts id 表示在ts时刻编号id的帖子收到一个"赞&qu ...

  7. 2018年第九届蓝桥杯 JavaB组省赛 刷题思路及答案

    前言 本人是二本院校大二的计算机系学生,已经报名了下一届的蓝桥杯省赛,整个寒假学习了很多算法知识,我是看<算法很美>这个课程学习算法的,一套学习下来确实受益匪浅,视频在b站上面都有. 此前 ...

  8. 第九届蓝桥杯大赛软件类国赛

    文章目录 第九届蓝桥杯大赛软件类国赛 国赛C++ A组 三角形面积 阅兵方阵 找假币 约瑟夫环 -- important 自描述序列 -- todo 采油 -- todo 国赛C++ B组 换零钞 激 ...

  9. 蓝桥杯的c语言编译器,第九届蓝桥杯大赛个人赛省赛(软件类)C/C++ 大学B组比赛心得(还在更新)...

    第九届蓝桥杯大赛个人赛省赛(软件类)C/C++ 大学B组 考生须知: 考试开始后,选手首先下载题目,并使用考场现场公布的解压密码解压试题. 考试时间为4小时.时间截止后,提交答案无效. 在考试强制结束 ...

最新文章

  1. javascript 自动按按钮
  2. redis-集群分片
  3. Matlab 图像分块(不重叠、重叠)
  4. python邮件添加附件_如何向电子邮件python添加多个附件
  5. 论文浅尝 | 弱监督关系抽取的深度残差学习方法
  6. 我们说的目标导向不是 “唯结果论”
  7. eclipse 打包 apk 文件
  8. 灵异事件很多,却没有平行宇宙
  9. cc2530设计性实验代码七
  10. Mock Server入门及实践
  11. Edxposed研究之Magisk源码下载编译的详细实战教程
  12. C语言编程学习使用auto定义变量的用法
  13. LeetCode 739. 每日温度(java实现)
  14. EFR32蓝牙串口透传程序流程
  15. Redis--慢查询的分析
  16. 关于主从复制的超详细解析(全)
  17. 云计算 第七章 云安全(3)概述 云计算面临的安全问题 云安全问题的深层原因 云安全关键技术 云计算信息安全的国内外标准化
  18. ironpython教程_用IronPython写winform程序-.NET教程,Asp.Net开发
  19. 计算机专业可以跨考哲学嘛,听成功跨考者自述 跨专业考研最需量体裁衣
  20. 各种音视频编解码学习详解(8)--Real系列

热门文章

  1. 前端三剑客HTML学习笔记
  2. GZIP文件格式简介
  3. 小学计算机趣味知识,小学生电脑课上都学哪些知识和操作?
  4. 国内首个网络安全行业全景图重磅推出
  5. OpenStack又有大变化?基金会官方一张图秒懂
  6. 自动驾驶路径规划技术-高速公路路径规划
  7. tag untag pvid 理解
  8. ica算法c语言,独立成分分析(ICA)的模拟实验(R语言)
  9. 明翰中高级Java后端面试题攻略v0.3(持续更新)
  10. 【电子电路】(1)PWM转DAC如何实现