zoukankan      html  css  js  c++  java
  • 【BZOJ3160】万径人踪灭(FFT,Manacher)

    【BZOJ3160】万径人踪灭(FFT,Manacher)

    题面

    BZOJ

    题解

    很容易想到就是满足条件的子序列个数减去回文子串的个数吧。。。

    至于满足条件的子序列
    我们可以依次枚举对称轴
    如果知道关于这个位置对称的位置的组数
    就很容易算了(直接(2^k-1)

    而关于这个位置对称是什么东西?
    (s[x-i]=s[x+i])
    也就是说,如果两个位置关于(x)位置对称,那么
    ((x-i)+(x+i)=2x)
    也就是两个位置的坐标的和等于(2x)
    这个玩意不就像一个卷积卷积了?

    那么,(a,b)分开考虑
    如果这个位置上有相应的字母就是(1)
    如果两个位置都有(1)
    那么,卷积(x+y)位置上就会有(1)
    这样就可以算出前面要求的东西了

    至于回文子串的个数?
    (Manacher)

    滑稽呀,马拉车写挂,身败名裂

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<complex>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 500000
    #define MOD 1000000007
    const double Pi=acos(-1);
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int len;
    char s[MAX];
    int p[MAX],N,M;
    ll Manacher()
    {
    	s[len+len+1]='#';s[0]='-';
    	for(int i=len;i;--i)
    	{
    		s[i*2]=s[i];
    		s[i*2-1]='#';
    	}
    	int mx=0,id=0;
    	for(int i=1;i<=len+len;++i)
    	{
    		p[i]=mx>i?min(p[id*2-i],mx-i):1;
    		while(s[i+p[i]]==s[i-p[i]])++p[i];
    		if(i+p[i]>mx)id=i,mx=p[i]+i;
    	}
    	ll ret=0;
    	for(int i=1;i<=len+len;++i)ret=(ret+p[i]/2)%MOD;
    	return ret;
    }
    int r[MAX],l;
    complex<double> a[MAX],b[MAX];
    ll f[MAX],tw[MAX],ans=0;
    void FFT(complex<double> *P,int opt)
    {
    	for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
    	for(int i=1;i<N;i<<=1)
    	{
    		complex<double> W(cos(Pi/i),opt*sin(Pi/i));
    		for(int p=i<<1,j=0;j<N;j+=p)
    		{
    			complex<double> w(1,0);
    			for(int k=0;k<i;++k,w*=W)
    			{
    				complex<double> X=P[j+k],Y=P[i+j+k]*w;;
    				P[j+k]=X+Y;P[i+j+k]=X-Y;
    			}
    		}
    	}
    }
    void Work(char cc)
    {
    	memset(a,0,sizeof(a));
    	memset(b,0,sizeof(b));
    	for(int i=1;i<=len;++i)a[i]=b[i]=s[i]==cc;
    	FFT(a,1);FFT(b,1);
    	for(int i=0;i<N;++i)a[i]*=b[i];
    	FFT(a,-1);
    	for(int i=1;i<N;++i)a[i].real()=a[i].real()/N+0.5;
    	for(int i=0;i<=M;++i)f[i]+=((int)(a[i].real())+1)/2;
    }
    int main()
    {
    	scanf("%s",s+1);
    	len=strlen(s+1);
    	M=len+len;
    	tw[0]=1;
    	for(int i=1;i<=M;++i)tw[i]=(tw[i-1]+tw[i-1])%MOD;
    	for(N=1;N<=M;N<<=1)++l;
    	for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    	Work('a');Work('b');
    	for(int i=1;i<=M;++i)ans=(ans+tw[f[i]]-1)%MOD;
    	ans=(ans-Manacher()+MOD)%MOD;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    HelpersRainCaptcha
    HelpersPHPMailer
    HelpersPassword
    HelpersPagination
    HelpersNumber
    HelpersHooks
    HelpersGeoCode
    HelpersFastCache
    HelpersDocument
    eclipse 设置jsp页面为HTML5
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8435460.html
Copyright © 2011-2022 走看看