bzoj 3160万径人踪灭

来源:互联网 发布:2017淘宝不好做 编辑:程序博客网 时间:2024/04/26 03:04

Ans=总方案数-回文对数

总方案数可以推出一个卷积形式

我真是哭晕在厕所。。。。Manacher i打成1看了1个多小时,交了无数遍才找到

/**************************************************************    Problem: 3160    User: Clare    Language: C++    Result: Accepted    Time:2092 ms    Memory:22368 kb****************************************************************/ #include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std; #define N 400010#define Mod 1000000007const double pi=acos(-1.0); int n,m;long long Ans;int Rev[N],p[N<<1],tmp[N],C[N];char S[N<<1];struct Complex{    double r,i;    Complex(){}    Complex(double r_,double i_):r(r_),i(i_){}    Complex operator + (const Complex &a) const{        return (Complex){r+a.r,i+a.i};    }    Complex operator - (const Complex &a) const{        return (Complex){r-a.r,i-a.i};    }    Complex operator * (const Complex &a) const{        return (Complex){r*a.r-i*a.i,r*a.i+i*a.r};    }}A[N],B[N]; inline int read(){    int x=0,f=1;char ch=getchar();    if(ch=='-')        f=-1,ch=getchar();    while(ch<='9'&&ch>='0')        x=x*10+ch-'0';ch=getchar();    return x*f;} int Manacher(){    for(int i=n;i>=0;i--)        S[i*2+1]='#',S[i*2+2]=S[i];    S[0]='$';    n=n*2+1;    int m=1,x=1,Sum=0;    for(int i=1;i<=n;i++)    {        p[i]=1;        if(i<m)            p[i]=min(m-i,p[x*2-i]);        while(S[i+p[i]]==S[i-p[i]])            p[i]++;        Sum=(Sum+(p[i]>>1))%Mod;        if(p[i]+i-1>m)            m=p[i]+i-1,x=i;    }    return Sum;} void FFT(Complex *a,int kind){    for(int i=0;i<n;i++)        if(i<Rev[i])swap(a[i],a[Rev[i]]);    for(int i=1;i<n;i<<=1)    {        Complex wn(cos(pi/i),sin(pi/i)*kind);        for(int len=i<<1,j=0;j<n;j+=len)        {            Complex w(1,0);            for(int k=0;k<i;k++)            {                Complex x=a[j+k],y=w*a[j+k+i];                a[j+k]=x+y;                a[j+k+i]=x-y;                w=w*wn;            }        }    }    if(kind==-1)    {        for(int i=0;i<n;i++)            a[i].r/=n;    }} int main(){    scanf("%s",S);    n=(int)strlen(S);    m=n+n-2;n=1;    int L=0;    while(n<=m)        n<<=1,L++;    for(int i=0;i<n;i++)        Rev[i]=(Rev[i>>1]>>1)|((i&1)<<(L-1));    memset(A,0,sizeof(A));    memset(B,0,sizeof(B));    for(int i=0;i<=m/2;i++)        if(S[i]=='a')A[i].r=1;    FFT(A,1);    for(int i=0;i<n;i++)        B[i]=A[i]*A[i];    FFT(B,-1);    for(int i=0;i<n;i++)        tmp[i]+=(int)(B[i].r+0.5);    memset(A,0,sizeof(A));    memset(B,0,sizeof(B));    for(int i=0;i<=m/2;i++)        if(S[i]=='b')A[i].r=1;    FFT(A,1);    for(int i=0;i<n;i++)        B[i]=A[i]*A[i];    FFT(B,-1);    for(int i=0;i<n;i++)        tmp[i]+=(int)(B[i].r+0.5);    C[0]=1;    for(int i=1;i<=300000;i++)        C[i]=C[i-1]*2%Mod;    for(int i=0;i<n;i++)        Ans=(Ans+C[(tmp[i]+1)/2]-1)%Mod;    n=m/2+1;    Ans=(Ans-Manacher()+Mod)%Mod;    cout<<Ans<<endl;    return 0;}


0 0