BZOJ3160: 万径人踪灭

n<=1e5的ab串,问对称的不连续的回文子序列数。取模。

虽然是道卷积题但是根本看不出来耶!

好吧没关系,要熟悉卷积那个图形:(红箭头那里是交于一点的,如果你觉得不是就是近视加深了)

好来看这个题,要是连续的可以用manacher得,所以不连续条件可先排除掉。

然后剩下的东西不就是要求这种形式的东西有多少个嘛!

说人话,$f(i)$表示对称轴为$\frac{i}{2}$的有多少对(0.5表示对称轴为两个字母的中间),$p[i]=[s[i]==a]$

那么$f_i=\sum_{j=0}^{i}1-(p_j \ \ xor \ \ p_{i-j})$,好的,卷积!等等这不是积。。

异或的话,先设a为1,b为0,卷积算一次,再a为0,b为1,卷积算一次,加起来不久得了。。

一个$f_i$对答案贡献是$2^{\left \lceil \frac{f_i}{2} \right \rceil}-1$

OK

话说这题还挺有诗意的,看背景以为是恐怖故事,结果全文一直用一种轻快的笔调来描述题意,丝毫没有别离带来的惆怅。这让我想起旧时候的分别诗句:“海内存知己,天涯若比邻”,“莫愁前路无知己,天下谁人不识君”,而笔者竟对别离一笔带过,可谓是更胜一筹!在轻描淡写的别离时配以浓墨重彩的景物描写,别离之愁需如此美景才可释怀,万径依在,人踪已灭,不仅使得别离的苦闷更加浓厚,还表现了一种旷达的胸襟,妙哉!(本题分类:语文)

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<complex>
 7 #include<math.h>
 8 //#include<iostream>
 9 using namespace std;
10 
11 int n,m,wei;
12 #define maxn 262222
13 char s[maxn];
14 const double pi=acos(-1);
15 const int mod=1e9+7;
16 typedef complex<double> cp;
17 cp a[maxn],b[maxn],c[maxn];
18 int two[maxn],p[maxn],rev[maxn];
19 
20 void dft(cp *a,int n,int type)
21 {
22     for (int i=0;i<n;i++) if (i<rev[i]) {cp t=a[i]; a[i]=a[rev[i]]; a[rev[i]]=t;}
23     for (int i=1;i<n;i<<=1)
24     {
25         cp base=cp(cos(pi/i),type*sin(pi/i));
26         for (int j=0,p=i<<1;j<n;j+=p)
27         {
28             cp t=cp(1,0);
29             for (int k=0;k<i;k++,t*=base)
30             {
31                 cp tmp=t*a[j+k+i];
32                 a[j+k+i]=a[j+k]-tmp;
33                 a[j+k]+=tmp;
34             }
35         }
36     }
37 }
38 
39 void mul(cp *a,cp *b)
40 {
41     if (!rev[1]) for (int i=0;i<n;i++)
42     {
43         rev[i]=0;
44         for (int j=0;j<wei;j++) rev[i]|=((i>>j)&1)<<(wei-j-1);
45     }
46     dft(a,n,1);
47     for (int i=0;i<n;i++) b[i]=a[i]*a[i];
48     dft(b,n,-1);
49     for (int i=0;i<n;i++) b[i]/=n;
50 }
51 
52 int main()
53 {
54     scanf("%s",s); n=strlen(s)-1;
55     m=n+n; for (n=1,wei=0;n<=m;n<<=1,wei++);
56     two[0]=1; for (int i=1;i<=m;i++) two[i]=(two[i-1]<<1)%mod;
57     m>>=1; for (int i=0;i<=m;i++) a[i]=(s[i]=='a'); m<<=1; mul(a,b);
58     m>>=1; for (int i=0;i<=m;i++) a[i]=(s[i]=='b');
59     for (int i=m+1;i<n;i++) a[i]=0; m<<=1; mul(a,c);
60     int ans=0;
61     for (int i=0;i<=m;i++) ans=(ans+two[((int)(b[i].real()+0.5)+(int)(c[i].real()+0.5)+1)>>1]-1)%mod;
62     
63     m>>=1; n=m+1; s[n+n]='$'; s[n+n+1]='\0';
64     for (int i=n-1;i>=0;i--) s[i+i+1]=s[i],s[i+i]='$';
65     p[0]=1; int id=0;
66     for (int i=1,to=n+n;i<to;i++)
67     {
68         if (p[id]+id>i) p[i]=min(p[id+id-i],p[id]+id-i); else p[i]=1;
69         while (p[i]+i<=to && i-p[i]>=0 && s[p[i]+i]==s[i-p[i]]) p[i]++;
70         if (i+p[i]>id+p[id]) id=i;
71         ans=(ans-(p[i]>>1)+mod)%mod;
72     }
73     printf("%d\n",ans);
74     return 0;
75 }
View Code

 

posted @ 2018-02-07 21:15  Blue233333  阅读(170)  评论(0编辑  收藏  举报