bzoj3160 万径人踪灭

来源:互联网 发布:greenplum数据库 编辑:程序博客网 时间:2024/05/29 16:45

3160: 万径人踪灭

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 814  Solved: 459
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

Sample Output

HINT

Source

2013湖北互测week1




吐槽:我替“千山鸟飞绝”感到不服。

manacher+FFT,思路好题

补集思想,直接求不连续的有点难,我们可以求出所有回文串,然后减去其中连续的。

连续回文串很好求,manacher就可以解决。

问题在于如何求不一定连续的回文串,如果求出以每个位置i为对称中心,对称的字符对的个数f[i],那对于答案的贡献就加上2^f[i]-1,证明很显然。

于是问题又成了如何求f[i]。

发现字符串中只有两种字符,而且对称的点的下标和为定值。于是我们可以先令a=1、b=0,再令a=0、b=1,分别用FFT求出卷积,就可以得到相等且下标和为x的字符对数。




#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#define F(i,j,n) for(int i=j;i<=n;i++)#define D(i,j,n) for(int i=j;i>=n;i--)#define ll long long#define maxn 300005#define mod 1000000007using namespace std;int n,len,ans,rev[maxn],f[maxn],bin[maxn];char s[maxn],st[maxn];const double pi=acos(-1.0);struct cp{double x,y;cp(double xx=0,double yy=0){x=xx;y=yy;}friend cp operator +(cp a,cp b){return cp(a.x+b.x,a.y+b.y);}friend cp operator -(cp a,cp b){return cp(a.x-b.x,a.y-b.y);}friend cp operator *(cp a,cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}}a[maxn],b[maxn];void fft(cp *x,int n,int flag){F(i,0,n-1) if (rev[i]>i) swap(x[i],x[rev[i]]);for(int m=2;m<=n;m<<=1){int mid=m>>1;cp wn(cos(2.0*pi/m*flag),sin(2.0*pi/m*flag));for(int i=0;i<n;i+=m){cp w(1.0,0);F(j,0,mid-1){cp u=x[i+j],v=x[i+j+mid]*w;x[i+j]=u+v;x[i+j+mid]=u-v;w=w*wn;}}}if (flag==-1) F(i,0,n-1) x[i].x/=n;}void manacher(){int mx=0,id=0;F(i,1,n){if (mx>i) f[i]=min(mx-i,f[id*2-i]);else f[i]=0;while (s[i+f[i]]==s[i-f[i]]) f[i]++;if (i+f[i]>mx) mx=i+f[i],id=i;ans=(ans-f[i]/2+mod)%mod;}}int main(){bin[0]=1;F(i,1,100000) bin[i]=bin[i-1]*2%mod;scanf("%s",s+1);len=strlen(s+1);n=1;int tmp=0;while (n<len*2) n<<=1,tmp++;F(i,1,n-1){rev[i]=rev[i>>1]>>1|((i&1)<<(tmp-1));}F(i,0,len-1) if (s[i+1]=='a') a[i].x=1;fft(a,n,1);F(i,0,n-1) a[i]=a[i]*a[i];fft(a,n,-1);F(i,0,len-1) if (s[i+1]=='b') b[i].x=1;fft(b,n,1);F(i,0,n-1) b[i]=b[i]*b[i];fft(b,n,-1);F(i,0,n-1){int x=round(a[i].x+b[i].x);x=(x+1)/2;ans=(ans+bin[x]-1)%mod;}F(i,1,len) st[i]=s[i];n=len<<1|1;s[0]='*';s[1]='#';s[n+1]='&';F(i,1,len) s[i<<1]=st[i],s[i<<1|1]='#';manacher();printf("%d\n",ans);return 0;}


0 0
原创粉丝点击