I Pa?sWorD

2023-09-19 02:47:45

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();//都不存在的情况,实际上这部分一定为0
    cout<<(sum%mod+mod)%mod<<endl;
}
signed main()
{
    Mirai;
    int T=1;
    //cin>>T;
    while(T--)
    {
        solve();
    }
}

更多推荐

Java实现单链表

目录一.单链表二.单链表基本操作的实现1.单链表类、属性的定义2.求链表长度3.链表是否包含值为key的节点4.添加元素5.删除节点6.清空链表三、完整代码一.单链表链表是一种在物理存储结构上非连续的存储结构,数据元素的逻辑顺序通过链表中的引用链接次序实现。链表的结构多样,我们通过实现无头单向非循环链表,来进一步理解链

【记录成长】大学时光已过半, 分享我的大二暑期实习经历

你好,我是cpt,本文章记录我大二暑期找实习的过程,以及工作中的点点滴滴,还有一些经验分享,希望能够帮助到你。实习投递(BOSS1k沟通10+面)投递我是2023.6.16才开始投递的当时真的很晚了基本很少hc而且小公司基本不要大二学生下面这两篇短文是当时面试遇到的问题25三本鼠鼠投500面试0难QAQ_牛客网请问各位

Opengl绘制三角形

节点对象学习:顶点数组对象:VertexArrayObject,VAO顶点缓冲对象:VertexBufferObject,VBO:表示存储在GPU显存中的大量顶点数据。我们可以通过这个对象,一次性向GPU发送大量的数据,而不是一次次地从CPU中发送数据到GPU,这是个很慢的过程。元素缓冲对象:ElementBuffer

三步实现Mybatis(Mybatis-Plus)多数据源配置

前言要实现多数据源可以采用dynamic-datasource或者mybatis-mate,本文就以dynamic-datasource为例dynamic-datasource简介springboot快速集成多数据源的启动器使用文档(opensnewwindow)支持数据源分组,适用于多种场景纯粹多库读写分离一主多从混

SpringBoot实战案例:图书管理系统

SpringBoot实战案例:图书管理系统在本文中,我们将介绍如何使用SpringBoot框架构建一个简单的图书管理系统。我们将从零开始,逐步完成系统的搭建。本文将分为以下七个部分:系统需求分析搭建项目框架实现数据访问层实现业务逻辑层实现控制层前端页面与交互测试与部署1.系统需求分析在开始构建图书管理系统之前,我们首先

SpringBoot-接口幂等性

幂等幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数或幂等方法是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。尤其是支付、订单等与金钱挂钩的服务,保证接口幂等性尤其重要。在实际开发中,我们需要针对不同的业务场景我们需要灵活的选

spring framework 5.2文档 - 控制反转 IoC 容器

IoC主题1.容器概述2.bean概述3.依赖注入(DI)4.Bean的范围5.定制一个beanSpring框架最重要的是控制反转(IoC)容器1.容器概述org.springframework.context.ApplicationContext接口代表SpringIoC容器,负责实例化、配置和组装bean。容器通过

竹云董事长董宁受邀出席香港第三届湾区元宇宙大会暨AIGC、RWA发展高峰论坛并作主题演讲

“一元初分,宇宙万仪”。9月16日,第三届湾区元宇宙大会暨AIGC、RWA发展高峰论坛在香港圆满落幕。全球权威机构、顶级专家学者、杰出企业家代表齐聚一堂,畅所欲言,全面总结分析元宇宙现状,综合研判元宇宙未来发展趋势。大会由香港区块链技术应用协会主办,粤港澳大湾区青年总会、香港国际投资总会、国际数据协会、联合国数字安全联

MySQL只同步单个表或多个表,非全部同步!

replicate-do-table是MySQL复制配置中的一个选项,它允许您指定要在从服务器上复制的表。如果您想要只复制主服务器上特定的表到从服务器,您可以使用这个选项。以下是如何操作replicate-do-table的步骤:停止从服务器:在从服务器上执行以下命令来停止复制:STOPSLAVE;编辑MySQL配置文

量化分析革新金融服务软件的三种方式

金融服务软件行业爱死量化分析了。为什么呢?因为在这个本质上不可预测的行业中,量化分析提供了一种确定性,或者至少是类似于确定性的东西。市场总是在变动,利润也起伏不定。交易达成了,然后落空,又再次达成,从交易大厅到董事会,纳秒级的差异可能成就巨大成功或带来重大损失。如果没有量化分析,我们难以预测这些事情会在何时、何地、以何

word快捷键、conda一些安装问题、坐标转换初阶

整理一下今天所学吧!用博客来记录还是比较理想的,因为可以时常观看。首先是word:上下标:ctrl+=,ctrl+shift+=斜体:ctrl+ialt+=插入公式!!!选中:shift+方向矩阵公式可以直接选中进行添加和修改。接着是一些环境:anaconda中,在c盘不好用时,去d盘打开首先需要给它初始化了:cond

热文推荐