【BZOJ3160】万径人踪灭
fft劲啊
题目太长,拒绝帖原题
一句话题意:
给一个ab串,求不连续的回文子序列的个数
看zars19的题解(和代码)写出来的
恩,回文子序列满足个性质,假设s[i]==s[j],他们的中点是mid
那么i+j==mid*2
卷积!
a设为1,b设为0自己卷一下,然后反过来b为1_a为0再卷一下
卷出来的a[i]表示以i为中心的最长回文子序列的长度
大概是酱紫:
判重的话(a[i]+1)/2就可以辣
但是这题目要求是不连续的回文子序列,fft搞出来的会有连续的
所以马拉车搞一搞,减去连续的回文子串即可
原来fft要开4倍,因为卷积卷完后差不多会增长一倍……(比如乘法是吧,手玩一下
注意马拉车也要开两倍
数组没开够没有1A
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 #define ll long long 8 const int dalao=1000000007; 9 struct cp{ 10 double r,i; 11 cp(double _r=0,double _i=0): r(_r),i(_i){} 12 cp operator+(cp x){return cp(r+x.r,i+x.i);} 13 cp operator-(cp x){return cp(r-x.r,i-x.i);} 14 cp operator*(cp x){return cp(r*x.r-i*x.i,r*x.i+i*x.r);} 15 }; 16 char s[410000],ss[410000]; int n,nn; 17 cp a[410000],b[410000],tmp[410000]; 18 int rvs[410000],dig[410000],N,L; 19 int f[410000]; 20 void fft(cp x[],int mk){ 21 for(int i=0;i<N;++i) tmp[i]=x[rvs[i]]; 22 for(int i=0;i<N;++i) x[i]=tmp[i]; 23 cp _x,_y,wn,w; 24 for(int i=2;i<=N;i<<=1){ 25 wn=cp(cos(2*M_PI/i),mk*sin(2*M_PI/i)); 26 for(int k=0;k<N;k+=i){ 27 w=cp(1,0); 28 for(int j=k;j<k+i/2;++j){ 29 _x=x[j]; _y=x[j+i/2]*w; 30 x[j]=_x+_y; x[j+i/2]=_x-_y; 31 w=w*wn; 32 } 33 } 34 } 35 if(mk==-1) for(int i=0;i<N;++i) x[i].r/=N; 36 } 37 ll mnch(){ 38 memset(f,0,sizeof(f)); 39 int mx=0,id=0; ll bwl=0; 40 for(int i=0;i<n;++i) ss[i<<1]='#',ss[i<<1|1]=s[i]; 41 ss[nn-1]='#'; 42 for(int i=0;i<nn;++i){ 43 f[i]=(mx>i ? min(f[(id<<1)-i],mx-i) : 1); 44 while(i>=f[i] && i+f[i]<nn && ss[i-f[i]]==ss[i+f[i]]) ++f[i]; 45 if(mx<f[i]+i-1) mx=f[i]+i-1,id=i; 46 bwl=(bwl+f[i]/2)%dalao; 47 } 48 return bwl; 49 } 50 ll qckpw(int x,int y){ 51 ll bs=x,bwl=1; 52 while(y){ if(y&1) bwl=(bwl*bs)%dalao; bs=(bs*bs)%dalao; y>>=1;} 53 return bwl; 54 } 55 int main(){//freopen("ddd.in","r",stdin); 56 //freopen("ddd.out","w",stdout); 57 scanf("%s",s); n=strlen(s),nn=n<<1|1; 58 for(N=1,L=0;N<n;N<<=1,++L); N<<=1,++L; 59 for(int i=0;i<N;++i){ 60 int l=0; 61 for(int j=i;j;j>>=1) dig[l++]=j&1; 62 for(int j=0;j<L;++j) rvs[i]=(rvs[i]<<1)|dig[j]; 63 } 64 for(int i=0;i<n;++i) a[i]=cp(s[i]=='a'),b[i]=cp(s[i]=='b'); 65 for(int i=n;i<N;++i) a[i]=b[i]=cp(0,0); 66 fft(a,1),fft(b,1); 67 for(int i=0;i<N;++i) a[i]=a[i]*a[i],b[i]=b[i]*b[i]; 68 fft(a,-1),fft(b,-1); 69 ll ans=0; int tmp; 70 for(int i=0;i<N;++i){ 71 tmp=((int)(a[i].r+b[i].r+0.5)+1)/2; 72 ans=(ans+qckpw(2,tmp)-1)%dalao; 73 } 74 ans=(ans+dalao-mnch())%dalao; 75 cout<<ans<<endl; 76 return 0; 77 }