做题时间:2026.7.25 题目难度:提高 | 题目链接 | 洛谷链接

我去忘了今天有 ABC 了!!!

10:20 才看到的题目,大概 10:30 就把思路秒了,今天的 G 咋这么简单啊?

这个题意思有点难懂(我借了 Qwen 才搞明白),就是如果第 ii 位是 o,则你的排列中必须包含一个 1i1 \sim i 的排列作为连续子序列,反之则必须不存在。

首先第 11 位和第 nn 位有 x 的话肯定无解。

我们考虑该字符串内的一个子串 oxxxo,由第一个 o 我们得知前面必为一个排列,那么我们就可以把这一整个排列视作一个元素重新进行计算,即计算完前面的方案数后直接删去前面的所有字符,并把最终答案乘上这个方案数后继续一轮新的计算。

很明显,我们需要处理很多类似 oxxxo 的字符串,并把它们的答案乘起来。

考虑令 fif_i 为字符串 ox...xo(包含 iix)的答案。这个我们可以用容斥来算,挺容易的。

整个题目下来好像没有什么难点。这还是 G 吗?

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2010,P=998244353;
int fac[N],f[N],g[N];char st[N];
signed main()
{
	int n;cin>>n;scanf("%s",st+1);
	fac[0]=1;for(int i=1;i<=n+1;i++)fac[i]=fac[i-1]*i%P;
	for(int i=1;i<=n;i++)
	{
		f[i]=fac[i+1];
		for(int j=1;j<i;j++)
			f[i]=((f[i]-f[j]*fac[i-j+1])%P+P)%P;
	}
	if(st[1]!='o'||st[n]!='o')
	{
		cout<<0;
		return 0;
	}
	int ans=1;
	for(int i=2,lst=1;i<=n;i++)if(st[i]=='o')
		ans=ans*f[i-lst]%P,lst=i;
	cout<<ans;
	return  0;
}