2019.7.13 义乌模拟赛 T2 string
作者:互联网
这个东西直接算显然不好算,我们考虑将其中心爆破。
如果我们枚举第三个位置\(l\),再枚举第四个字符\(c0\),那么一二位的方案数是平凡的。
考虑如果时间复杂度允许,我们枚举第五个位置\(r\),设\(S(c,l,r)\)为\([l,r]\)中\(c\)的数量,那么答案就是\(S(c,l,r)\times S(c,r,n)\)
但是这样时间会爆掉。
我们倒序枚举,对于每个位置,它的答案与离他后面最近的点的答案有一定关联性,具体的,都增加了两点间距离乘上前缀和。
那这东西随便维护一下即可。时间复杂度\(O(nm)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 1000000
#define M 65
#define mod 998244353
#define eps (1e-8)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m=62,Sum[N+5][M+5],Sm[M+5],G[N+5],A[N+5],las[M+5];ll ans,LA[M+5][M+5],F[M+5][M+5],now,tot,pus;char s[N+5];
I ll calc(ll x){return x*(x-1)/2%mod;}
int main(){
freopen("string.in","r",stdin);freopen("string.out","w",stdout);
re int i,j;scanf("%s",s+1);n=strlen(s+1);for(i=0;i<26;i++) G[i+'a']=i+1,G[i+'A']=i+27;for(i=0;i<10;i++)G[i+'0']=i+53;
for(i=1;i<=n;i++) A[i]=G[s[i]],tot+=Sm[A[i]],Sm[A[i]]++;for(i=n;i;i--) memcpy(Sum[i],Sum[i+1],sizeof(Sum[i])),Sum[i][A[i]]++;
for(i=n;i;i--){
Sm[A[i]]--;tot-=Sm[A[i]];now=(Sm[A[i]]-1)*Sm[A[i]]/2%mod-tot%mod;now=(now%mod+mod)%mod;
for(j=1;j<=m;j++){if(j==A[i]) continue;
pus=calc(i-Sm[A[i]]-Sm[j]-1)+Sm[j]*(Sm[j]-1)/2%mod;
if(las[A[i]])LA[A[i]][j]=(LA[A[i]][j]+F[A[i]][j]*(Sum[i][j]-Sum[las[A[i]]][j]))%mod;
F[A[i]][j]=(Sum[i][j]+F[A[i]][j])%mod;ans+=LA[A[i]][j]*(now+pus)%mod;
}las[A[i]]=i;//printf("%lld\n",ans);
}printf("%lld\n",(ans%mod+mod)%mod);
}
标签:13,string,int,ll,2019.7,枚举,mod,define 来源: https://www.cnblogs.com/275307894a/p/15009177.html