LG P4199 万径人踪灭
Description
在只含a,b的字符串中,求满足以下条件的子序列个数:
- 位置和字符关于某条对称轴对称
- 不能是连续的一段
Solution
答案可以转化为关于某条对称轴对称的子序列-连续的回文串
连续的回文串可以用Manacher求出
关于某条对称轴对称的子序列可以FFT求出:将原字符串中为a的位置设为1,b的位置设为0,该多项式自平方后第$i$位即为以$\frac{i}{2}$为对称轴,左右两边相同位置为a的对数$x$,b同理,则分奇偶讨论可得以该对称轴为中心有$2^{x+1}-1$或$2^x-1$个字母组合满足条件
FFT多项式相乘
#include<iostream> #include<cstring> #include<complex> #include<cstdio> #include<cmath> using namespace std; long long len,rev[400005],tot=1,s=2,ans[400005],r[400005],sum; const long long mod=1000000007; const double pi=acos(-1); char str[400005],sn[400005]; complex<double>an[400005],bn[400005]; inline long long read() { long long w=0,f=1; char ch=0; while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { w=(w<<1)+(w<<3)+ch-'0'; ch=getchar(); } return w*f; } void fft(complex<double>*a,long long n,long long inv) { for(long long i=0;i<n;i++) { if(i<rev[i]) { swap(a[i],a[rev[i]]); } } for(long long i=1;i<n;i<<=1) { complex<double>wn=exp(complex<double>(0,inv*pi/i)); for(long long j=0;j<n;j+=i*2) { complex<double>w(1,0); for(long long k=j;k<i+j;k++) { complex<double>x=a[k],y=w*a[k+i]; a[k]=x+y; a[k+i]=x-y; w*=wn; } } } if(inv==-1) { for(long long i=0;i<n;i++) { a[i]/=n; } } } long long ksm(long long a,long long p) { long long ret=1ll; while(p) { if(p&1) { (ret*=a)%=mod; } (a*=a)%=mod; p>>=1; } return ret; } void manacher() { long long nlen=0,maxx=0,maxlen=-1,id; sn[nlen]='$'; sn[++nlen]='#'; for(long long i=0;i<len;i++) { sn[++nlen]=str[i]; sn[++nlen]='#'; } sn[++nlen]='\0'; for(long long i=1;i<=nlen;i++) { if(i<maxx) { r[i]=min(r[2*id-i],maxx-i); } else { r[i]=1; } while(sn[i-r[i]]==sn[i+r[i]]) { ++r[i]; } if(maxx<i+r[i]) { maxx=i+r[i]; id=i; } ((sum-=(r[i]>>1))+=mod)%=mod; } } int main() { scanf("%s",str); len=strlen(str); for(long long i=0;i<len;i++) { an[i]=(double)(str[i]=='a'); bn[i]=(double)(str[i]=='b'); } while((1<<tot)<(len<<1)) { ++tot; s<<=1; } for(long long i=0;i<s;i++) { rev[i]=(rev[i>>1]>>1)|((i&1)<<(tot-1)); } fft(an,s,1); fft(bn,s,1); for(long long i=0;i<s;i++) { an[i]*=an[i]; bn[i]*=bn[i]; } fft(an,s,-1); fft(bn,s,-1); for(long long i=0;i<s;i++) { ans[i]+=(long long)(an[i].real()+0.5); ans[i]+=(long long)(bn[i].real()+0.5); if(!(i&1)) { ++ans[i]; } ans[i]>>=1; } for(long long i=0;i<=2*len-2;i++) { ans[i]=ksm(2,ans[i])-1; } manacher(); for(long long i=0;i<=2*len-2;i++) { (sum+=ans[i])%=mod; } printf("%lld\n",sum); return 0; }