题意:
解法:
题 意 其 实 就 是 要 你 计 算 有 多 少 个 形 如 C D A B A B 的 子 序 列 . 考 虑 O ( n ) 枚 举 A , 那 么 方 案 数 为 左 边 的 C D 数 量 乘 上 右 边 的 B A B 数 量 . 右 边 B A B 数 量 可 以 先 计 算 A B 数 量 , 利 用 A B 数 量 计 算 B A B 数 量 . 左 边 C D 数 量 = X Y 数 量 − A X − B X − X A − X B + A B + B A . A B + B A = 左 边 A 的 数 量 乘 上 左 边 B 的 数 量 . 左 边 X Y 数 量 啥 的 可 以 O ( n ∗ 60 ) 利 用 d p 预 处 理 . 算 法 总 复 杂 度 O ( n ∗ 60 ) . 题意其实就是要你计算有多少个形如CDABAB的子序列.\\ 考虑O(n)枚举A,那么方案数为左边的CD数量乘上右边的BAB数量.\\ 右边BAB数量可以先计算AB数量,利用AB数量计算BAB数量.\\ 左边CD数量=XY数量-AX-BX-XA-XB+AB+BA.\\ AB+BA=左边A的数量乘上左边B的数量.\\ 左边XY数量啥的可以O(n*60)利用dp预处理.\\ 算法总复杂度O(n*60). 题意其实就是要你计算有多少个形如CDABAB的子序列.考虑O(n)枚举A,那么方案数为左边的CD数量乘上右边的BAB数量.右边BAB数量可以先计算AB数量,利用AB数量计算BAB数量.左边CD数量=XY数量−AX−BX−XA−XB+AB+BA.AB+BA=左边A的数量乘上左边B的数量.左边XY数量啥的可以O(n∗60)利用dp预处理.算法总复杂度O(n∗60).
code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxm=1e6+5;
const int mod=998244353;
char s[maxm];
int a[maxm];
int sum1[66][66];//AB的数量.
int sum2[66][66];//BAB的数量.
int cnt[66];
int f1[maxm][66];//[1,i]以Y结尾的XY数量.
int f2[maxm][66];//[1,i]以X开头的XY数量.
int cc[maxm][66];//[1,i]中X的数量.
int tot[maxm];//[1,i]中XY的总数量.
int n;
int cal(char c){
if(c>='0'&&c<='9')return c-'0';
else if(c>='a'&&c<='z')return c-'a'+10;
else return c-'A'+36;
}
inline void add(int &a,int b){
a+=b;
while(a>=mod)a-=mod;
while(a<0)a+=mod;
}
inline void DP(){
int ans=0;
for(int i=n;i>=3;i--){
for(int j=0;j<62;j++){
if(j==a[i])continue;
add(sum2[a[i]][j],sum1[j][a[i]]);
add(sum1[a[i]][j],cnt[j]);
}
cnt[a[i]]++;
for(int j=0;j<62;j++){
if(j==a[i])continue;
int temp=tot[i-1];
add(temp,-f1[i-1][a[i]]);
add(temp,-f1[i-1][j]);
add(temp,-f2[i-1][a[i]]);
add(temp,-f2[i-1][j]);
add(temp,1ll*cc[i-1][a[i]]*cc[i-1][j]%mod);
add(ans,1ll*sum2[j][a[i]]*temp%mod);
}
}
printf("%d\n",ans);
}
inline void solve(){
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;i++)a[i]=cal(s[i]);
for(int i=1;i<=n;i++){
for(int j=0;j<62;j++){
cc[i][j]=cc[i-1][j];
f1[i][j]=f1[i-1][j];
f2[i][j]=f2[i-1][j];
}
cc[i][a[i]]++;
for(int j=0;j<62;j++){
if(j==a[i])continue;
add(f1[i][a[i]],cc[i-1][j]);
add(f2[i][j],cc[i-1][j]);
}
for(int j=0;j<62;j++){
add(tot[i],f1[i][j]);
}
}
DP();
}
signed main(){
solve();
return 0;
}