版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/88829069
分析:
还是比较板的多项式老题
这题唯一花哨一点的,就是要求回文串不能全部连续。
而我们知道,全部连续的话可以用manachar算出来。
那么剩下的就是算所有的回文子序列的方案数了。
显然fft一发,对每个位置,算出其左边和右边对称的个数,记为
那么以i为中心的回文子序列数量就是
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 600010
#define MOD 1000000007
using namespace std;
typedef long long ll;
const double Pi=acos(-1);
struct cpx{
double r,i;
cpx () {}
cpx (double r1,double i1):r(r1),i(i1) {}
cpx operator +(const cpx &a) const {
return cpx(r+a.r,i+a.i);
}
cpx operator -(const cpx &a) const {
return cpx(r-a.r,i-a.i);
}
cpx operator *(const cpx &a) const {
return cpx(r*a.r-i*a.i,r*a.i+i*a.r);
}
}A[MAXN],B[MAXN];
void FFT(cpx A[],int N,int flag){
for(int i=1,j=0;i<N;i++){
for(int d=N;j^=d>>=1,~j&d;);
if(i<j)
swap(A[i],A[j]);
}
for(int i=1;i<N;i<<=1){
cpx wn=cpx(cos(Pi/i),flag*sin(Pi/i));
for(int j=0;j<N;j+=(i<<1)){
cpx w=cpx(1,0);
for(int k=0;k<i;k++,w=w*wn){
cpx x=A[j+k],y=w*A[i+j+k];
A[j+k]=x+y;
A[i+j+k]=x-y;
}
}
}
if(flag==-1){
for(int i=0;i<N;i++)
A[i].r/=N;
}
}
void mul(cpx A[],cpx B[],int n,int m,cpx res[]){
static cpx tmp1[MAXN],tmp2[MAXN];
for(int i=0;i<n;i++)
tmp1[i]=A[i];
for(int i=0;i<m;i++)
tmp2[i]=B[i];
int p=1;
while(p<=n+m)
p<<=1;
FFT(tmp1,p,1);
FFT(tmp2,p,1);
for(int i=0;i<p;i++)
res[i]=tmp1[i]*tmp2[i];
FFT(res,p,-1);
for(int i=0;i<p;i++)
tmp1[i]=tmp2[i]=cpx(0,0);
}
int f[MAXN],g[MAXN];
char s1[MAXN],s[MAXN];
int solve(char s[],int n){
int mid=1,pos=1;
for(int i=1;i<n;i++){
g[i]=min(g[2*mid-i],pos-i+1);
while(s[i+g[i]]==s[i-g[i]]){
g[i]++;
mid=i;
pos=i+g[i]-1;
}
}
}
ll fsp(ll x,int y){
ll res=1;
while(y){
if(y&1)
res=res*x%MOD;
x=x*x%MOD;
y>>=1;
}
return res;
}
int main(){
int n,m;
SF("%s",s1);
n=strlen(s1);
s[0]='$';
for(int i=0;i<n;i++)
s[++m]='#',s[++m]=s1[i];
s[++m]='#';
s[++m]='@';
n=m+1;
for(int i=0;i<n;i++)
A[i].r=1.0*(s[i]=='a'),B[i].r=1.0*(s[i]=='b');
mul(A,A,n,n,A);
mul(B,B,n,n,B);
for(int i=0;i<n;i++)
f[i]=int(A[i*2].r+0.5)+int(B[i*2].r+0.5);
// for(int i=0;i<n;i++)
// PF("%d(%c) ",f[i],s[i]);
for(int i=1;i<n;i++){
if(i%2==0)
f[i]++;
f[i]/=2;
}
int tot=solve(s,n);
ll ans=0;
for(int i=1;i<n;i++){
g[i]=g[i]>>1;
// PF("[%d %d]\n",f[i],g[i]);
ans=(ans+fsp(2,f[i])-1-g[i]+MOD)%MOD;
}
PF("%lld",ans);
}