首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

【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 }
View Code

 

posted on 2017-03-07 21:50  cdcq_old  阅读(206)  评论(2编辑  收藏  举报