乐山市网站建设_网站建设公司_网站备案_seo优化
2026/1/19 19:34:46 网站建设 项目流程

题目链接

大概就是寻找不变量,发现若把 \(\texttt a\) 看成 \(1\)\(\texttt b\) 看成 \(2\),则总和 \(\bmod 3\) 的值不变。

然后考虑对这些 \(1\)\(2\) 的前缀和数组 \(a\)(下标 \(0 \sim n\))进行操作,发现等价于每次删掉一个数,要求其两边的数不同。

接着可以推出把一个长度 \(> 0\) 的区间 \([l, r]\) 删空的条件有

  1. \(a _ l \neq a _ r\)

  2. \([l - 1, r + 1]\) 中至少包含 \(3\) 种数。

现在可以把题目转化成选择 \(a\) 的本质不同合法子序列,且必须选 \(0\)\(n\) 的方案数。

这可以类似本质不同子序列,设计一个 dp(形似被动转移的 dp 套 dp),\(f _ i\) 能从 \(f _ j\) 转移过来当且仅当对于 \(a _ j\) 相同的所有位置中,\(j\) 是最大的使得开区间 \((j, i)\) 能被删空的位置,答案就是 \(f _ n\)

初值怎么赋?dp 套 dp 的思想只是最大化子序列开头位置,但我们的要求是 \(0\) 必须选。但我们有惊人的结论:若 \(a\) 中存在 \(3\) 种数,则对于任意 \(a _ i \neq 0\)\(f _ i\) 初值为 \(1\);否则答案为 \(1\)。这可以通过调整法证明,如下图:

#include<cstdio>
#include<cstring>
#define N 100005
using namespace std;const int mod=1e9+7;
int n,a[N],f[N],las[3],las2[3][3];
char s[N];
int main() {scanf("%s",s+1),n=strlen(s+1);for(int i=1;i<=n;i++) a[i]=(a[i-1]+(s[i]=='a'?1:2))%3;for(int i=1;i<=n;i++) {f[i]=((a[i]!=0)+f[i-1]+f[las2[3-a[i]-a[i-1]][a[i-1]]])%mod;las[a[i]]=i;for(int j=0;j<3;j++) if(j!=a[i]) las2[j][a[i]]=las[j];}printf("%d\n",las[1]&&las[2]?f[n]:1);return 0;
}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询