题目

传送门

题目大意

如果两个只包含数字且长度为 \(n\) 的字符串 \(s\) 和 \(w\) 存在两个数字 \(1≤i,j≤n\),使得 \(s_i<w_i,s_j>w_j\) ,则称 \(s\) 和 \(w\) 是不可比的。现在给定两个包含数字和问号且长度为 \(n\) 的字符串,问有多少种方案使得将所有问号替换成 \(0\) 到 \(9\) 的数字后两个字符串是不可比的?

思路

分析

DP 题, 我们注意到,只要有一对这样的数就可以满足条件,而等于是不属于判断情况的,因此我们要单独记一个状态。

状态

f[i][k]: 当在第 $i$ 位时,第 $k$ 种情况的方案数。
以下: j < i
k = 0 : 前面只出现了 s[j] < w[j] 的情况,并没有 s[j] > w[j] ,即 s[j] <= w[j]
k = 1 : 前面 s[j] < w[j] , s[j] > w[j]
k = 2 : 前面只出现了 s[j] > w[j] 的情况,并没有 s[j] < w[j] ,即 s[j] >= w[j]
k = 3 : 前面只有 s[j] == w[j] 情况

转移

我们要对每一位考虑该位上填每个数字的情况。

对于已经确定数字的位,我们要只要对该数字讨论。

如果有'?',我们要枚举 1~9 进行转移。

感觉有点像数位DP?

初始状态

f[0][3] = 1

代码

按照各种状态进行转移即可,代码量有点大。

当然,也有一种代码量小的解法,可以预先算出每种情况转移,就不必枚举。

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string> #define ll long long
using namespace std; const int MAXN = 1e5+10;
const ll mod = 1e9+7; int n;
ll f[MAXN][4];
char s[MAXN],w[MAXN]; int main (){
scanf("%d",&n);
scanf("%s",s+1);
scanf("%s",w+1);
f[0][0] = f[0][1] =f[0][2] = 0;
f[0][3] = 1;
for(int i = 1;i <= n;i++){
if(s[i] != '?' &&w[i] != '?'){
if(s[i] > w[i]) {
f[i][0] = 0;
f[i][1] = f[i-1][0] + f[i-1][1];
f[i][2] = f[i-1][2] + f[i-1][3];
f[i][3] = 0;
} else if(s[i] == w[i]){
f[i][0] = f[i-1][0];
f[i][1] = f[i-1][1];
f[i][2] = f[i-1][2];
f[i][3] = f[i-1][3];
} else{
f[i][0] = f[i-1][0] + f[i-1][3];
f[i][1] = f[i-1][2] + f[i-1][1];
f[i][2] = 0;
f[i][3] = 0;
}
} else if(s[i] == '?' && w[i] != '?'){
for(int j = '0';j < w[i] ;j++){
f[i][0] += f[i-1][0] + f[i-1][3];
f[i][1] += f[i-1][1] + f[i-1][2];
f[i][2] += 0;
}
f[i][0] += f[i-1][0];
f[i][1] += f[i-1][1];
f[i][2] += f[i-1][2];
f[i][3] += f[i-1][3];
for(int j = w[i] + 1;j <= '9';j++){
f[i][1] += f[i-1][0] + f[i-1][1];
f[i][2] += f[i-1][2] + f[i-1][3];
}
} else if(s[i] != '?' && w[i] == '?'){ for(int j = '0' ;j < s[i] ;j++){
f[i][1] += f[i-1][0] + f[i-1][1];
f[i][2] += f[i-1][2] + f[i-1][3];
}
f[i][0] += f[i-1][0];
f[i][1] += f[i-1][1];
f[i][2] += f[i-1][2];
f[i][3] += f[i-1][3];
for(int j = s[i] +1;j <= '9' ;j++){
f[i][0] += f[i-1][0] + f[i-1][3];
f[i][1] += f[i-1][1] + f[i-1][2];
}
} else{
for(int j = 0;j < 10;j++){
for(int k = 0;k < 10;k++){
if(j<k){
f[i][0] += (f[i-1][0] + f[i-1][3])%mod;
f[i][1] += (f[i-1][1] + f[i-1][2])%mod;
} else if(j == k){
f[i][0] += f[i-1][0];
f[i][1] += f[i-1][1];
f[i][2] += f[i-1][2];
f[i][3] += f[i-1][3];
} else{
f[i][1] += (f[i-1][0] + f[i-1][1])%mod;
f[i][2] += (f[i-1][2] + f[i-1][3])%mod;
}
f[i][0] %= mod;
f[i][1] %= mod;
f[i][2] %= mod;
}
}
}
f[i][0] %= mod;
f[i][1] %= mod;
f[i][2] %= mod;
}
printf("%d",f[n][1] % mod);
return 0;
}

题解 CF296B 【Yaroslav and Two Strings】的更多相关文章

  1. Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings (容斥原理)

    题目链接 Description Yaroslav thinks that two strings s and w, consisting of digits and having length n  ...

  2. 最长重复字符串题解 golang

    最长重复字符串题解 package main import ( "fmt" "strings" ) type Index map[int]int type Co ...

  3. Codeforces Round #179 (Div. 1 + Div. 2)

    A. Yaroslav and Permutations 值相同的个数不能超过\(\lfloor \frac{n + 1}{2} \rfloor\). B. Yaroslav and Two Stri ...

  4. 题解-ARC058D Iroha Loves Strings

    题面 ARC058D Iroha Loves Strings 给定 \(n\) 个字符串,从中选出若干个按给出顺序连接起来,总长等于 \(m\),求字典序最小的,保证有解. 数据范围:\(1\le n ...

  5. 题解-Reachable Strings

    题解-Reachable Strings 前置知识: \(\texttt{Hash}\) Reachable Strings 给一个长度为 \(n\) 的 \(\texttt{01}\) 串 \(s\ ...

  6. [LeetCode]题解(python):043-Multiply Strings

    题目来源 https://leetcode.com/problems/multiply-strings/ Given two numbers represented as strings, retur ...

  7. 【题解】Power Strings

    题目描述 给定若干个长度小于等于10^6的字符串,询问每个字符串最多由多少个相同的子串重复连接而成.如:ababab,最多由3个ab连接而成. 输入输出格式 输入格式 若干行,每行一个字符串. 当读入 ...

  8. Power Strings[poj2406]题解

    Power Strings Description - Given two strings a and b we define ab to be their concatenation. For ex ...

  9. CF1320 Div1 D.Reachable Strings 题解

    题目大意 给定一个长为\(n\)的01串\(S\),每次你可以对一个串的三个连续位置做:\(011 \rightarrow 110\),\(110 \rightarrow 011\)的操作. 有\(q ...

随机推荐

  1. android面试详解

    前台就是和用户交互的进程 可见进程例如一个activity被一个透明的对话框覆盖,该activity就是可见进程 服务:service进程 后台一个activity按了home按键就是从前台退回到后台 ...

  2. java中值传递

    最近学基础的时候,老师讲了值传递和引用传递,这个问题一直不太明白,上网查了很多资料,按照自己的理解整理了一遍,发现之前不太明白的地方基本上想明白了,如有不正确的地方,欢迎指正,谢谢. 首先要说明的是j ...

  3. Netdiscover

    Netdiscover不仅支持主动arp检测,还支持被动的arp检测,即把网卡设置为混杂模式,收取所有局域网内的arp广播数据包,从而判断活着的ip. 主动发现命令格式:netdiscover  -i ...

  4. Python 分布式缓存之Reids数据类型操作

    目录 1.Redis API 2.String 操作 3.Hash 操作 4.List 操作 1.Redis API 1.操作模式 redis-py提供两个类Redis和StrictRedis用于实现 ...

  5. tkinter的三种几何布局管理类

    1.pack() 主要采用块的方式组织子组件 如下: import tkinter root=tkinter.Tk() #创建窗口对象 label=tkinter.Label(root,text='h ...

  6. CentOS 的命令链接符“;”

    ";" 用于在一行中输入多个命令,执行顺序=输入顺序. For instance: $ ls -a;cd Music

  7. Oracle Solaris 11.4安装桌面/gdb

    文章目录 1. 说明 2. 挂载镜像 3. 安装桌面 4. 安装gdb 5. 重启OS 1. 说明 该文承接上文Solaris 11.4安装,映像包管理系统(IPS)搭建. Solaris 11.4的 ...

  8. JVM源码分析之堆内存的初始化

    原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 “365篇原创计划”第十五篇. ​ 今天呢!灯塔君跟大家讲: JVM源码分析之堆内存的初始化   堆初始化 Java堆的初始化入口位于Univ ...

  9. WIN10有线网络反复断开解决方法

    最近家里台式机碰到一个奇怪的问题,开机之后有线网络就时断时续,右下角网络图标不停在小地球与小电脑之间切换.网上大概搜索了一下,貌似碰到这种问题的朋友不在少数,但大部分朋友碰到的都是无线网络居多.这里把 ...

  10. Mybatis源码初探——优雅精良的骨架

    @ 目录 前言 精良的Mybatis骨架 宏观设计 基础支撑 日志 日志的加载 日志的使用 数据源 数据源的创建 池化技术原理 数据结构 获取连接 回收连接 缓存 缓存的实现 CacheKey 反射 ...