I
题意:
给出一个串,可能?、小写字母,大写字母、数字。
小写字母可以变成当前小写字母的小写或者大写形式。
数字和大写只能是当前形式。
问号可以变成另外三种形式。
现在要求相同的字符不相邻,且字符串中同时出现三种字符形式的方案数。
设dp[i][j][k],表示第i个位置为j,且当前状态为k的方案数。
k是状压的形式:[0 0 0]三个位置分别表示数字、小写和大写,其范围为[0,7]
当前的位置j通过映射,[1~62]对应[0 ~ 9, a ~ z, A ~ Z]
转移方程:
对于每个k和当前的h进行下列方程转移。
然而这样如果遇到问号,复杂度是转移,过不了。
这里考虑先对于每个k,提前把处理好,然后对对应的h,特别的减去,写作下式:
则复杂度转化为
#include<bits/stdc++.h> using namespace std; #define IOS ios::sync_with_stdio(0),cin.tie(0) #define int long long const int N = 1e5+7; int dp[2][80][10],tmp[10]; char ch[80]; map<char,int>mp; const int mod = 998244353; int st(int y) { char x=ch[y]; if(isdigit(x)) { return 1; } if(islower(x)) { return 2; } if(isupper(x)) { return 4; } return 0; } signed main() { IOS; int n; cin>>n; string s; cin>>s; s=' '+s; int cnt=0; for(int i=0;i<=9;i++) { ch[++cnt]=i+'0'; mp[i+'0']=cnt; } for(char x='a';x<='z';x++) { ch[++cnt]=x; mp[x]=cnt; } for(char x='A';x<='Z';x++) { ch[++cnt]=x; mp[x]=cnt; } int id=mp[s[1]]; if(st(id)==0) { //问号 for(int i=1;i<=62;i++) { dp[1][i][st(i)]=1; } }else if(st(id)==1) { //数字 dp[1][id][st(id)]=1; }else if(st(id)==2) { //小写 dp[1][id][st(id)]=1; dp[1][id+26][st(id+26)]=1; }else if(st(id)==4) { //大写 dp[1][id][st(id)]=1; } int cur=1; for(int i=2;i<=n;i++) { for(int k=1;k<=7;k++) { tmp[k]=0; } for(int j=1;j<=62;j++) { for(int k=1;k<=7;k++) { //把所有k相同的状态做前缀和转移 tmp[k]+=dp[cur][j][k]; tmp[k]%=mod; //滚动数组清空 dp[cur^1][j][k]=0; } } int now=mp[s[i]]; for(int k=1;k<=7;k++) { if(st(now)==0) { for(int id=1;id<=62;id++) { //问号的时候,枚举当前 dp[cur^1][id][k|st(id)]+=tmp[k]-dp[cur][id][k]; dp[cur^1][id][k|st(id)]=(dp[cur^1][id][k|st(id)]%mod+mod)%mod; } }else if(st(now)==1) { //[1,10] int id=mp[s[i]]; dp[cur^1][id][k|st(id)]+=tmp[k]-dp[cur][id][k]; dp[cur^1][id][k|st(id)]=(dp[cur^1][id][k|st(id)]%mod+mod)%mod; }else if(st(now)==2) { //小写 int id=mp[s[i]]; dp[cur^1][id][k|st(id)]+=tmp[k]-dp[cur][id][k]; dp[cur^1][id][k|st(id)]=(dp[cur^1][id][k|st(id)]%mod+mod)%mod; id+=26; dp[cur^1][id][k|st(id)]+=tmp[k]-dp[cur][id][k]; dp[cur^1][id][k|st(id)]=(dp[cur^1][id][k|st(id)]%mod+mod)%mod; }else if(st(now)==4) { //大写 int id=mp[s[i]]; dp[cur^1][id][k|st(id)]+=tmp[k]-dp[cur][id][k]; dp[cur^1][id][k|st(id)]=(dp[cur^1][id][k|st(id)]%mod+mod)%mod; } } cur=cur^1; } int maxn=0; for(int i=1;i<=62;i++) { maxn=maxn+dp[cur][i][7]; maxn%=mod; } cout<<maxn<<endl; }
本文作者:TimMCBen
本文链接:https://www.cnblogs.com/TimMCBen/p/17713224.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步