2025.3.29 NOIP模拟赛

news/2025/4/1 7:02:34/文章来源:https://www.cnblogs.com/XP3301Pipi/p/18799784

2025.3.29 NOIP模拟赛

Problem C. 传统艺能

Description

给定一个长为 \(n\) 的字符串,只含有 \(\texttt{A,B,C}\)

\(Q\) 次操作,单点修改,区间查询 \([l,r]\) 中本质不同的子序列个数。

\(\mathcal{O(nq)}\) Solution

\(f_i\)\(A[1\sim i]\) 中本质不同子序列个数。

如果 \(a_i\) 前面没有与其相同的字符,那么 \(f_i=2_{i-1}+1\)

否则,如果仍然以上面的方式转移,考虑哪些子序列会被算重。

假设现在有两个子序列 \(\texttt{ABCB}\)\(\texttt{ABCBC}\),且 \(a_i=\texttt{C}\)。那么如果给前面一个子序列接上 \(\texttt{C}\),那么就会重复。

\(lst_x\)\(x\) 这个字符上一次出现的位置。我们把 \(A[1\sim lst_{a_i}]\) 中所有子序列拿出来,在后面接上 \(a_i\),可以得到所有重复的子序列。那么重复的个数应为 \(f_{lst_{a_i}-1}\)

于是得到转移 \(f_i=2f_{i-1}-f_{lst_{a_i}-1}\)

我们对每一次询问从 \(l\)\(r\) 做一次 \(O(n)\) 的 dp 即可。

\(\mathcal{O(q\log n)}\) Solution

我们换一种 dp 方式:令 \(f_i\)\(i\) 结尾 的子序列个数。

设字符串中在 \(i\) 之前出现的最后一个 \(\texttt{A,B,C}\) 的位置分别为 \(preA,preB,preC\)

那么有转移:\(f_i=f_{preA}+f_{preB}+f_{preC}+1\)

设整个字符串中出现的最后一个 \(\texttt{A,B,C}\) 的位置为 \(lstA,lstB,lstC\),答案为 \(f_{lstA}+f_{lstB}+f_{lstC}\)

发现我们这个时候可以把每一个位置的 \(f\) 写为一个矩阵:

\[\begin{bmatrix}fa_i&fb_i&fc_i&1\end{bmatrix} \]

其中 \(fa_i,fb_i,fc_i\) 分别表示 \(i\) 处的 \(f_{lstA},f_{lstB},f_{lstC}\)

那么对于 \(a_i=\texttt{A,B,C}\),分别列出转移矩阵:

\[MA=\begin{bmatrix}1&0&0&0\\1&1&0&0\\1&0&1&0\\1&0&0&1\end{bmatrix},MB=\begin{bmatrix}1&1&0&0\\0&1&0&0\\0&1&1&0\\0&1&0&1\end{bmatrix},MC=\begin{bmatrix}1&0&1&0\\0&1&1&0\\0&0&1&0\\0&0&1&1\end{bmatrix} \]

线段树维护矩阵乘法即可。

int n,Q;
char a[N];const ll mod=998244353;struct Matrix{ll val[4][4];
}ept,MA,MB,MC,X,st;inline ll Mod(ll x){return (x>=mod)?(x-mod):(x);
}inline void Add(ll& x,ll y){x=Mod(x+y);
}void Init(){MA.val[0][0]=1,MA.val[0][1]=0,MA.val[0][2]=0,MA.val[0][3]=0;MA.val[1][0]=1,MA.val[1][1]=1,MA.val[1][2]=0,MA.val[1][3]=0;MA.val[2][0]=1,MA.val[2][1]=0,MA.val[2][2]=1,MA.val[2][3]=0;MA.val[3][0]=1,MA.val[3][1]=0,MA.val[3][2]=0,MA.val[3][3]=1;MB.val[0][0]=1,MB.val[0][1]=1,MB.val[0][2]=0,MB.val[0][3]=0;MB.val[1][0]=0,MB.val[1][1]=1,MB.val[1][2]=0,MB.val[1][3]=0;MB.val[2][0]=0,MB.val[2][1]=1,MB.val[2][2]=1,MB.val[2][3]=0;MB.val[3][0]=0,MB.val[3][1]=1,MB.val[3][2]=0,MB.val[3][3]=1;MC.val[0][0]=1,MC.val[0][1]=0,MC.val[0][2]=1,MC.val[0][3]=0;MC.val[1][0]=0,MC.val[1][1]=1,MC.val[1][2]=1,MC.val[1][3]=0;MC.val[2][0]=0,MC.val[2][1]=0,MC.val[2][2]=1,MC.val[2][3]=0;MC.val[3][0]=0,MC.val[3][1]=0,MC.val[3][2]=1,MC.val[3][3]=1;st.val[0][3]=1;
}Matrix operator*(Matrix x,Matrix y){Matrix z=ept;for(int k=0;k<4;k++)for(int i=0;i<4;i++)for(int j=0;j<4;j++)Add(z.val[i][j],x.val[i][k]*y.val[k][j]%mod);return z;
}Matrix tr[N<<2];void Pushup(int p){tr[p]=tr[p<<1]*tr[p<<1|1];
}void Buildtr(int p,int l,int r){if(l==r){if(a[l]=='A') tr[p]=MA;else if(a[l]=='B') tr[p]=MB;else tr[p]=MC;return;}int mid=(l+r)>>1;Buildtr(p<<1,l,mid);Buildtr(p<<1|1,mid+1,r);Pushup(p);
}void Update(int p,int l,int r,int x){if(l==r) return tr[p]=X,void();int mid=(l+r)>>1;if(x<=mid) Update(p<<1,l,mid,x);else Update(p<<1|1,mid+1,r,x);Pushup(p);
}Matrix Ask(int p,int l,int r,int L,int R){if(L<=l&&r<=R) return tr[p];int mid=(l+r)>>1;if(L<=mid&&mid<R)return Ask(p<<1,l,mid,L,R)*Ask(p<<1|1,mid+1,r,L,R);else if(L<=mid) return Ask(p<<1,l,mid,L,R);else return Ask(p<<1|1,mid+1,r,L,R);
}signed main(){read(n),read(Q);Init();scanf("%s",a+1);Buildtr(1,1,n);while(Q--){int op; read(op);if(op==1){int x; char c[3];read(x),scanf("%s",c);if(c[0]=='A') X=MA,Update(1,1,n,x);else if(c[0]=='B') X=MB,Update(1,1,n,x);else X=MC,Update(1,1,n,x);}else{int l,r; read(l),read(r);Matrix res=st*Ask(1,1,n,l,r);ll ans=Mod(Mod(res.val[0][0]+res.val[0][1])+res.val[0][2]);printf("%lld\n",ans);}}return 0;
}

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

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

相关文章

JavaScript 数据结构与算法 — 单向链表

链表(Linked List)是一种基本的数据结构,用于表示一组按顺序排列的元素。链表中的每个元素都与下一个元素连接,元素在内存中并不是连续的,而是通过指针来链接在一起。每个元素都包含两部分:自己的数据和指向下一个元素的指针。我们常说的链表指的是单向链表,第一个元素的…

Ethernaut通关(智能合约漏洞)(有缘更新)

SnowSword笑传之出错币Ethernaut通关 参考文章:文章 - Ethernaut闯关录(上) - 先知社区、 智能合约是什么?把智能合约想象成网络上的赛博自动售货机,每个人都可以写自己的智能合约,使用虚拟货币交易物品,并且网络区块链中的所有节点都在为你的交易记账不怕商家提桶跑路……

QML基本组件 滑动条 Slider

描述 Slider通过手柄沿轨迹滑动来设置数值。 Qt帮助文档搜索 “slider” 获取详细信息。属性 from : real to : real value : real orientation : enumeration stepsize : real touchDragThreshold : qreal信号 onValueChange {}import QtQuick import QtQuick.ControlsWindow …

UE5--006--小结(一)

1. Input2. AI Enmy3.Save Game

阶段升级,zhitan-ems开源能源管理系统--集成建筑能耗支路和分项功能

升级介绍 自从春节上班后开源以来,zhitan-ems收到了大家很多的赞誉和认可,很多朋友也提出了中肯的意见。感谢大家。 很多朋友的建议里提到建筑能耗功能,依据大家意见,我们加班加点实现了简单的建筑能耗功能。如下图: 另外打一波广告,欢迎大家star 项目介绍 通过物联网技…

Static Timing Analysis Basics

Preface This note only introduce the essential concepts about Static Timing Analysis, which not contains:Async, i.e. remove, recover Timing conceptions, i.e. false path, multi cycle path etc. Advance timing domain knowledgePOCV, MCMM etc.什么是 STA 由于时钟…

深圳大学的一些简单题

A打表,发现是这样的东西:然后规律很显然,相邻的两个数,一组在左边,另一组在右边,依次循环,偶数的时候是 \(23\) 开头,奇数的时候是 \(12\) 开头,再处理一下 \(1\) 和 \(n\) 就可以,比较简单的分讨 显然规律不止一个点击查看代码 #include <bits/stdc++.h> usin…

AI可解释性 I | 对抗样本(Adversarial Sample)论文导读(持续更新)

本文作为AI可解释性系列的第一部分,旨在以汉语整理并阅读对抗攻击(Adversarial Attack)相关的论文,并持续更新。与此同时,AI可解释性系列的第二部分:归因方法(Attribution)也即将上线,敬请期待。AI可解释性 I | 对抗样本(Adversarial Sample)论文导读(持续更新) 导…

day:33 jmeter性能测试——压力测试

一.单接口性能测试(同一用户进行压力测试) POST http://49.233.201.254:8080/cms/manage/loginJump.do POST data: userAccount=admin&loginPwd=123456(1)在线程中修改虚拟用户数线程组 线程数:虚拟用户数。一个虚拟用户占用一个进程或线程。设置多少虚拟用户数在这里…

c#winform,倒鸭子字幕,仿AE软件的typemonkey插件,类似抖音的瀑布流字幕

不废话 直接上效果图C# winform 开发 类似抖音的瀑布流字幕。也是类似AE软件的typemonkey插件或者咱再网上常说的倒鸭子字幕 主要功能 1,软件可以自定义添加字幕内容2,软件可以添加字幕显示的时间区间3,可以自定义字幕颜色,可以随机颜色4,支持字幕的上下调节5,支持字幕的…

20241110 实验二《Python程序设计》实验报告

学号 2024-2025-2 《Python程序设计》实验二报告 课程:《Python程序设计》 班级: 2411 姓名: 王方俊 学号:20241110 实验教师:王志强 实验日期:2025年3月26日 必修/选修: 公选课 一、实验内容 (一)设计并完成一个计算器,支持整数和复数,可以完成加、减、乘、除、对数…

打造用户认证系统,构筑信息安全防线

在当今的数字化时代,信息安全和用户隐私保护变得越来越重要。用户身份认证是确保信息安全的第一道防线。通过验证用户身份,可以防止未经授权的访问和数据泄露。它有助于保护用户的个人信息、账户资金和其他敏感数据。此外,用户身份认证还可以提高系统的安全性,减少恶意行为…