2019牛客多校第五场 G subsequence 1 dp+组合数学
subsequence 1
题意
给出两个数字串s,t,求s的子序列中在数值上大于t串的数量
分析
数字大于另一个数字,要么位数多,要么位数相同,字典序大,位数多可以很方便地用组合数学来解决,所以只剩下了位数相同的情况,如何实现呢,我们考虑定义状态dp[i][j][0/1]分别表示s串前i个字符中长度为j的串前面的字符等于t串相应长度的前缀的数量,1则表示大于的数量 ,然后分三种情况转移即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll P=998244353;
const int maxn=3005;
const int M=3005;
char s[maxn],t[maxn];
ll dp[maxn][maxn][2];
ll F[maxn],Finv[maxn],inv[maxn];
ll pw(ll bs,ll x){
ll ans=1;
while(x){
if(x&1)ans=ans*(bs%P)%P;
bs=bs*(bs%P)%P;
x>>=1;
}
return ans;
}
void init(){
F[1]=Finv[1]=inv[1]=Finv[0]=inv[0]=1;
for(int i=2;i<M;i++)inv[i]=inv[P%i]*(P-P/i)%P;
for(int i=2;i<M;i++){
Finv[i]=Finv[i-1]*inv[i]%P;
F[i]=F[i-1]*i%P;
}
}
ll C(int n,int m){
if(m<0||n<m)return 0;
if(m==0||n==m)return 1;
return F[n]%P*(Finv[n-m]%P)%P*Finv[m]%P;
}
int main(){
int n,m;
int T;
scanf("%d",&T);
init();
while(T--){
scanf("%d%d",&n,&m);
scanf("%s%s",s+1,t+1);
for(int i=0;i<=n;i++)for(int j=0;j<=m;j++)for(int k=0;k<2;k++)dp[i][j][k]=0;
dp[0][0][0]=1;
for(int i=1;i<=n;i++){
dp[i][1][0]=dp[i-1][1][0];
dp[i][1][1]=dp[i-1][1][1];
if(s[i]==t[1]&&t[1]!='0'){dp[i][1][0]++;dp[i][1][0]%=P;}
if(s[i]>t[1]){dp[i][1][1]++;dp[i][1][1]%=P;}
for(int j=2;j<=max(m,i);j++){
if(s[i]<t[j]){
dp[i][j][0]=dp[i-1][j][0];
dp[i][j][1]=(dp[i-1][j][1]+dp[i-1][j-1][1])%P;
}
else if(s[i]==t[j]){
dp[i][j][0]=(dp[i-1][j][0]+dp[i-1][j-1][0])%P;
dp[i][j][1]=(dp[i-1][j-1][1]+dp[i-1][j][1])%P;
}
else if(s[i]>t[j]){
dp[i][j][1]=(dp[i-1][j-1][0]+dp[i-1][j-1][1]+dp[i-1][j][1])%P;
dp[i][j][0]=dp[i-1][j][0];
}
}
}
long long sum=dp[n][m][1];
/*for(int i=m;i<=n;i++){
sum=dp[i][m][1];sum%=P;
}*/
for(int i=1;i<=n-m;i++){
if(s[i]=='0')continue;
for(int j=m;j<=n-i;j++){
sum+=C(n-i,j);sum%=P;
}
}
printf("%lld\n",sum);
//cout<<sum<<endl;
/*for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<"1 :"<<dp[i][j][1]<<" 0: "<<dp[i][j][0]<<" ||";
}
cout<<endl;
}*/
}
return 0;
}
2019牛客多校第五场 G subsequence 1 dp+组合数学的更多相关文章
- 2019牛客多校第五场H - subsequence 2 拓扑
H - subsequence 2 题意 要你使用前\(m\)个小写字母构造一个长度为\(n\)的字符串 有\(m*(m-1)/2\)个限制条件: \(c_{1} .c_{2}. len\):表示除去 ...
- 牛客多校第五场 G subsequence 1 最长公共子序列/组合数
题意: 给定两个由数字组成的序列s,t,找出s所有数值大于t的子序列.注意不是字典序大. 题解: 首先特判s比t短或一样长的情况. 当s比t长时,直接用组合数计算s不以0开头的,长度大于t的所有子序列 ...
- 2019牛客多校第五场 generator 1——广义斐波那契循环节&&矩阵快速幂
理论部分 二次剩余 在数论中,整数 $X$ 对整数 $p$ 的二次剩余是指 $X^2$ 除以 $p$ 的余数. 当存在某个 $X$,使得式子 $X^2 \equiv d(mod \ p)$ 成立时,称 ...
- 2019牛客多校第五场generator2——BSGS&&手写Hash
题目 几乎原题 BZOJ3122题解 分析 先推一波公式,然后除去特殊情况分类讨论,剩下就是形如 $a^i \equiv b(mod \ p)$ 的方程,可以使用BSGS算法. 在标准的BSGS中,内 ...
- 2019牛客多校第五场F maximum clique 1 最大独立集
题意:给你n个数,现在让你选择一个数目最大的集合,使得集合中任意两个数的二进制表示至少有两位不同,问这个集合最大是多大?并且输出具体方案.保证n个数互不相同. 思路:容易发现,如果两个数不能同时在集合 ...
- 2019牛客多校第五场G-subsequence 1 DP
G-subsequence 1 题意 给你两个字符串\(s.t\),问\(s\)中有多少个子序列能大于\(t\). 思路 令\(len1\)为\(s\)的子序列的长度,\(lent\)为\(t\)的长 ...
- 2019牛客多校第五场 B - generator 1 矩阵快速幂+十倍增+二进制倍增优化
B - generator 1 题意 给你\(x_{0}.x_{1}.a.b.b.mod\),根据\(x_{i} = a*x_{i-1} + b*x_{i-2}\)求出\(x_{n}\) 思路 一般看 ...
- 2019牛客多校第五场B-generator 1(矩阵快速幂)
generator 1 题目传送门 解题思路 矩阵快速幂.只是平时的矩阵快速幂是二进制的,这题要用十进制的快速幂. 代码如下 #include <bits/stdc++.h> #defin ...
- 2019 牛客多校第五场 B generator 1
题目链接:https://ac.nowcoder.com/acm/contest/885/B 题目大意 略. 分析 十进制矩阵快速幂. 代码如下 #include <bits/stdc++.h& ...
随机推荐
- java基础之----23种设计模式(单例模式)
概述 提到单例模式,我们并不陌生,而且面试中也常常会问单例模式相关的问题,接下来就谈谈单例模式,这篇文章会回答如下几个问题: 什么是单例模式? 单例模式有几种实现方式,以及各种实现方式的优劣? 单例模 ...
- Linux学习记录(二):常用工具
博主使用的操作系统为Ubuntu tmux 终端分屏 安装 Ubuntu使用apt-get安装 sudo apt-get install tmux 使用 默认命令键:Ctrl + B %(百分号) 左 ...
- 三种比较好玩的黑客效果JS代码(摘取)
<html> <head> <title>The Matrix</title> <script src="http://ajax.goo ...
- perfdog使用手册
PerfDog(性能狗)测试须知 Android平台 ScreenShot(只支持USB模式) FPS(1秒内游戏画面或者应用界面真实平均刷新次数,俗称帖率/FPS) 1)Avg(FPS):平均帖率 ...
- 数据类型(8种)和运算符——Java
一.什么是标识符,它有什么作用(重点掌握) 1. 标识符指的是 标识符是用户编程时使用的名字,用于给变量.常量.函数.语句块等命名,以建立起名称与使用之间的关系.标识符可由任何字母数字字符串形成. 2 ...
- gulp常用插件之gulp-rev-delete-origina使用
更多gulp常用插件使用请访问:gulp常用插件汇总 gulp-rev-delete-origina这是一款删除由gulp-rev或 gulp-rev-all重写的原始文件 . 更多使用文档请点击访问 ...
- EF Code-First(Oracle)通过Migration来更新数据库的表的字段
关于Oracle中使用Entity Framework 6.x Code-First方式开发,请参考博客(菩提树下的杨过)https://www.cnblogs.com/yjmyzz/p/how-to ...
- Python类的特殊成员方法
__doc__ 类的描述信息. class dog: '''这是狗的类''' def __init__(self,name): self.name = name self.__age = None p ...
- H5_0012:js事件冒泡和捕获
捕获(capture)和冒泡(bubble)是事件传播过程中的两个概念, 比如用户单击某个元素, 但由于元素处于父元素内, 该父元素又处于document对象中, document对象又处于windo ...
- 《Python学习手册 第五版》 -第14章 迭代和推导
承接上一章for循环的讲解,迭代和推导,是对for循环的一种深入的探索和扩展 本章重点内容 1.迭代 1)什么是迭代?都有哪些分类 2)常规的使用方法 3)多遍迭代器VS单遍迭代器 2.列表推导 1) ...