题目链接
题目大意
两个人打乒乓,一个人实力较弱,给出他们一共打了 n n n个球,用一个字符串 S S S表示每一场的胜负情况,所以他来骗来偷袭更改规则①为当赢 k k k个球时获胜(原来为11个),统计他赢的场数 f x f_x fx,并要求 ∑ i = 1 ∣ S ∣ f i ∗ ( n + 1 ) i − 1 \sum_{i=1}^{|S|}f_i*(n+1)^{i-1} ∑i=1∣S∣fi∗(n+1)i−1.
题解
这题是一个朴实无华的模拟,运用了自动机的思想。
我们枚举每个
k
k
k的数,即从
1
1
1 ~
n
n
n,用数组储存当前位置信息,因为每个球只能影响到后面的求解,故我们运用前缀和来计算它的值。
我们找到每一场开头和结尾②,将每一场的总获胜数和输球数进行比较即可。
记得乘方用快速幂计算,还有一定要取模哦!
注:
①
国际乒乓球的规则是每场起码打到
11
11
11个球,且获胜球数较对方至少大于
1
1
1,若差值为
1
1
1,则加赛至差值大于
1
1
1。
②
由于加赛的特殊性,所以我们需要一个数组
B
B
B来储存类似KMP的东西找到下一个改变球差的位置,使得保证能得出结果。
参考代码
#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
const int MAXN=1e6+5;
int n,sumW[MAXN],sumL[MAXN],posW[MAXN],posL[MAXN],B[MAXN];
char S[MAXN];
int powmod(int x,int p){ //快速幂
int ret=1;
while(p){
if(p&1)ret=1ll*ret*x%mod;
x=1ll*x*x%mod;
p>>=1;
}
return ret;
}
int main()
{
std::ios::sync_with_stdio(false),cin.tie(0);
cin>>n;
cin>>S+1;
int u=0,v=0,last=n+1;
for(int i=1;i<=n;i++) //初始化
{
sumW[i]=sumW[i-1]+(S[i]=='W');
sumL[i]=sumL[i-1]+(S[i]=='L');
if(S[i]=='W')posW[++u]=i;
else posL[++v]=i;
}
B[n]=n+1;
for(int i=n-1;i>=0;i--) //②处
{
if(S[i]==S[i+1])last=i+1;
B[i]=last;
}
int ans=0;
for(int k=1;k<=n;k++)
{
int s=0,ss,sum=0;
while(sumW[s]+k<=u||sumL[s]+k<=v) //模拟
{
if(s>n)break;
if(sumW[s]+k>u) //若赢的球被拿完
{
ss=posL[sumL[s]+k];
int i=(sumL[ss]-sumL[s])-(sumW[ss]-sumW[s]);
if(abs(i)<2)
{
while(abs(i)<2)
{
if(ss>n)break;
ss=B[ss];
i=(sumL[ss]-sumL[s])-(sumW[ss]-sumW[s]);
}
if(ss>n)break;
s=ss;
if(S[s]=='W')sum++;
}
else s=ss;
}
else if(sumL[s]+k>v) //若输的球被拿完
{
ss=posW[sumW[s]+k];
int i=(sumL[ss]-sumL[s])-(sumW[ss]-sumW[s]);
if(abs(i)<2)
{
while(abs(i)<2)
{
if(ss>n)break;
ss=B[ss];
i=(sumL[ss]-sumL[s])-(sumW[ss]-sumW[s]);
}
if(ss>n)break;
s=ss;
if(S[s]=='W')sum++;
}
else s=ss,sum++;
}
else if(posW[sumW[s]+k]<posL[sumL[s]+k]) //若获胜球数多
{
ss=posW[sumW[s]+k];
int i=(sumL[ss]-sumL[s])-(sumW[ss]-sumW[s]);
if(abs(i)<2)
{
while(abs(i)<2)
{
if(ss>n)break;
ss=B[ss];
i=(sumL[ss]-sumL[s])-(sumW[ss]-sumW[s]);
}
if(ss>n)break;
s=ss;
if(S[s]=='W')sum++;
}
else s=ss,sum++;
}
else //若获胜球数少
{
ss=posL[sumL[s]+k];
int i=(sumL[ss]-sumL[s])-(sumW[ss]-sumW[s]);
if(abs(i)<2)
{
while(abs(i)<2)
{
if(ss>n)break;
ss=B[ss];
i=(sumL[ss]-sumL[s])-(sumW[ss]-sumW[s]);
}
if(ss>n)break;
s=ss;
if(S[s]=='W')sum++;
}
else s=ss;
}
}
ans=(ans+1ll*sum*powmod(n+1,k-1)%mod)%mod;
}
cout<<ans<<endl;
return 0;
}