I Pa?sWorD

2023icpc网络赛第一场 I

题意:题目给出只包含大小写字母,数字以及'?'的字符串,对于每一个小写字母,这一位字符既有可能是该小写字母,也有可能是该小写字母的对应大写字母,也就是该位的字符有两种可能,对于问号,可能是所有大写字母或者所有小写字母,或者所有单数字,则共有62种情况,而对于大写字母和数字位则都是确定的只有这一种情况

要求输出最后符合以下条件的字符串共有多少种

1、至少有一个小写字母

2、至少有一个大写字母

3、至少有一个数字位

4、相邻的两个字符不能相同

思路:容斥原理+线性dp

我们暂且先不管前三个要求,对于要求4,可以通过线性dp来解决,我们定义dp[i][j]为以第i位为结尾并且结尾这一位选择j(定义1-26代表大写字母,27-52为小写字母,53-62为数字位,63代表该位的所有情况的总和,63最后单独处理)共有多少种情况,则对于某一位选某一个字符的情况数即为前一位的总情况数减去前一位也选相同字符的情况数,则有状态转移方程:

dp[i][j]=dp[i-1][63]-dp[i-1][j]

然而题目中给出了对于内存的限制,通过观察不难发现每一次状态更新只与前一层有关,所以考虑将dp数组降维

此时我们再来解决前三个条件,对于之前提到的线性dp,我们可以得到在不考虑大小写字母以及数字位是否都存在的所有符合条件4的合法情况数,但其中是存在违反条件1-3的情况的,我们现在要做的是将这些情况不重不漏(划重点)的减去,这样我们就可以得到最终结果,这时就要应用到容斥原理:

我们将这些情况(已知所有符合条件4的情况中违反条件1-3的所有情况)抽象成以下图形,其中圈1为一定不包括大写字母的所有情况,圈2为一定不包括小写字母的所有情况,圈3为一定不包括数字位的所有情况,那么现在问题就是要求出这三个圆的共同覆盖面积并减去,

这时我们通过规定是否一定不存在大写字母、小写字母或者数字位对线性dp进行限制并求得在该条件下的情况数,具体实现方式见代码

而当我们分别减去一定不存在大写字母,一定不存在小写字母,一定不存在数字位这三种情况的方案数之后,对于该图形中的每个小图形具体减了几次见下图

这时我们又发现中间有一部分多减了,所以我们又要将部分图形给加回来,此时我们发现可以通过加每两个圆的公共部分来将结果进一步推进,对于一定不存在大写字母并且一定不存在数字位的图形范围为:

将三个圆的两两公共部分都加回来之后对于每个小图形的减去次数可表示为:

此时我们不难发现只需要将三种字符都一定不存在的情况减去就可以了(实际上这部分根本不存在,所以减不减无所谓)

最后的效果:

ac代码:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define INF 0x3f3f3f3f
#define pb push_back
#define int long long
// #define int unsigned long long
#define Mirai ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
typedef pair<int,int> pii;
const int N=1e5+10,mod=998244353;
int dp[2][100];//1-26 大写字母 27-52 小写字母 53-62 数字 63 总和
int b[3];
int n;
string s;
int get()
{memset(dp,0,sizeof dp);dp[0][63]=1;for(int i=1;i<=n;i++){for(int j=1;j<=63;j++)dp[i&1][j]=0;if(s[i]>='A'&&s[i]<='Z')//大写{if(b[0])return 0;dp[i&1][s[i]-'A'+1]=dp[(i-1)&1][63]-dp[(i-1)&1][s[i]-'A'+1];}else if(s[i]>='0'&&s[i]<='9')//数字{if(b[2])return 0;dp[i&1][s[i]-'0'+53]=dp[(i-1)&1][63]-dp[(i-1)&1][s[i]-'0'+53];}else if(s[i]>='a'&&s[i]<='z')//小写{if(b[0]&&b[1])return 0;if(!b[1])dp[i&1][s[i]-'a'+27]=dp[(i-1)&1][63]-dp[(i-1)&1][s[i]-'a'+27];if(!b[0])dp[i&1][s[i]-'a'+1]=dp[(i-1)&1][63]-dp[(i-1)&1][s[i]-'a'+1];;}else //问号{  for(int j=1;j<=62;j++){if(b[0]&&j>=1&&j<=26)continue;if(b[1]&&j>=27&&j<=52)continue;if(b[2]&&j>=53)continue;dp[i&1][j]=dp[(i-1)&1][63]-dp[(i-1)&1][j];}}for(int j=1;j<=62;j++)(dp[i&1][63]+=dp[i&1][j]%mod)%=mod;}return dp[n&1][63];
}
void solve()
{cin>>n;cin>>s;s=" "+s;int sum=get();b[0]=1,b[1]=0,b[2]=0,sum-=get();b[0]=0,b[1]=1,b[2]=0,sum-=get();b[0]=0,b[1]=0,b[2]=1,sum-=get();b[0]=1,b[1]=1,b[2]=0,sum+=get();b[0]=1,b[1]=0,b[2]=1,sum+=get();b[0]=0,b[1]=1,b[2]=1,sum+=get();// b[0]=1,b[1]=1,b[2]=1,sum-=get();//都不存在的情况,实际上这部分一定为0cout<<(sum%mod+mod)%mod<<endl;
}
signed main()
{Mirai;int T=1;//cin>>T;while(T--){solve();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/112298.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电商项目高级篇-01 elasticsearch

电商项目高级篇-01 elasticsearch 1、linux下安装elasticsearch和可视化工具 1、linux下安装elasticsearch和可视化工具 将安装好jdk1.8和tomcat的centos7下安装elasticsearch docker pull elasticsearch:7.4.2docker pull kibana:7.4.2##docker下安装软件需要配置挂载。方便…

基于matlab实现的多普勒脉冲雷达回波仿真

完整程序&#xff1a; clear all;clc;close all; fc3e9; %载波频率 PRF2000; Br5e6; %带宽 fs10*Br; %采样频率 Tp5e-6; %脉宽 KrBr/Tp; %频率变化率 c3e8; %光速 lamda…

MySQL查询表结构方法

MySQL查询数据库单个表结构代码 – 查询数据库表信息 SELECT​ COLUMN_NAME 列名,​ DATA_TYPE 字段类型,​ CHARACTER_MAXIMUM_LENGTH 长度,​ IS_NULLABLE 是否为空,​ IF(column_key PRI,Y,) 是否为主键,​ COLUMN_DEFAULT 默认值,​ COLUMN_COMMENT 备注FROM​ INFORMAT…

线性矩阵不等式(LMI)在控制理论中的应用

目录 &#xff08;一&#xff09;Matlab中的LMI处理工具包 &#xff08;二&#xff09;为什么LMI成为控制理论领域重要工具&#xff1f; &#xff08;三&#xff09;LMI在与Lyapunov不等式的关系 &#xff08;1&#xff09;线性矩阵不等式 &#xff08;2&#xff09;线性矩阵…

PHP8的类与对象的基本操作之成员方法-PHP8知识详解

成员方法是指在类中声明的函数。 在类中可以声明多个函数&#xff0c;所以对象中可以存在多个成员方法。类的成员方法可以通过关键字进行修饰&#xff0c;从而控制成员方法的商用权限。 函数和成员方法唯一的区别就是&#xff0c;函数实现的是某个独立的功能&#xff0c;而成…

电脑怎么取消磁盘分区?

有时候&#xff0c;我们的电脑会出现一个磁盘爆满&#xff0c;但另一个却空着&#xff0c;这时我们可以通过取消磁盘分区来进行调整&#xff0c;那么&#xff0c;这该怎么操作呢&#xff1f;下面我们就来了解一下。 磁盘管理取消磁盘分区 磁盘管理是Windows自带的磁盘管理工具…

【uniapp】Dcloud的uni手机号一键登录,具体实现及踩过的坑,调用uniCloud.getPhoneNumber(),uni.login()等

一键登录Dcloud官网请戳这里&#xff0c;感兴趣的可以看看官网&#xff0c;有很详细的示例&#xff0c;选择App一键登录&#xff0c;可以看到一些常用的概述 比如&#xff1a; 1、调用uni.login就能弹出一键登录的页面 2、一键登录的流程&#xff0c;可以选择先预登录uni.prelo…

Jmeter接口测试简易步骤

使用Jmeter接口测试 1、首先右键添加一个线程组&#xff0c;然后我们重命名接口测试 2、在线程组上添加一个Http默认请求&#xff0c;并配置服务器的IP地址端口等信息 3、在线程组中添加一个HTTP请求&#xff0c;这里我们重命名“增加信用卡账户信息接口” 4、配置接口请求信息…

服务网格和性能优化:介绍如何通过服务网格提高微服务架构的性能和可扩展性

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

【Git】03-GitHub

文章目录 1. GitHub核心功能2. GitHub搜索项目3. GitHub搭建个人博客4. 团队项目创建5. git工作流选择5.1 需要考虑的因素5.2 主干开发5.2 Git Flow5.3 GitHub Flow5.4 GitLab Flow(带生产分支)5.4 GitLab Flow(带环境分支)5.4 GitLab Flow(带发布分支) 6. 分支集成策略7. 启用…

Linux学习记录——이십팔 网络基础(1)

文章目录 1、了解2、网络协议栈3、TCP/IP模型4、网络传输1、同一局域网&#xff08;子网&#xff09;2、局域网通信原理3、跨一个路由器的两个子网4、其它 详细的网络发展历史就不写了 1、了解 为什么会出现网络&#xff1f;一开始多个计算机之间想要共享文件&#xff0c;就得…

【蓝桥杯选拔赛真题60】Scratch旋转风车 少儿编程scratch图形化编程 蓝桥杯选拔赛真题解析

目录 scratch旋转风车 一、题目要求 编程实现 二、案例分析 1、角色分析