zoukankan      html  css  js  c++  java
  • 【BZOJ3160】万径人踪灭

    题面

    imgimgimgimg

    题目分析

    我们来看一看一个回文串满足什么:

    对于回文串,如果中点一定,所有以它为中点的点对下标之和也一定。

    我们设下标为(i),点对个数之和为(f(i)),则方案数为(2^{f(i)}-1)

    显然有(f(x)=((sumlimits_{i=1}^{x-1}[s[i]=s[x-i]])+1)/2)

    其中(sumlimits_{i=1}^{x-1}[s[i]=s[x-i]])可以视作一个卷积的形式;

    我们指定字符,如a,则把(s[i]=)a的位置赋初值为(1),然后进行卷积即可。

    因此,(f(x))的答案为指定字符分别为a,b的卷积结果之和(+1/2)

    代码实现

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<cstdio>
    #include<iomanip>
    #include<cstdlib>
    #include<complex>
    #define MAXN 0x7fffffff
    typedef long long LL;
    const int N=400005,mod=1e9+7;
    using namespace std;
    inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;}
    typedef complex<double> Z;
    const double Pi=M_PI;
    void FFT(Z *a,int x,int K){
    	static int rev[N],lst;
    	int n=1<<x;
    	if(n!=lst){
    		for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<x-1);
    		lst=n;	
    	}
    	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){
    		int tmp=i<<1;
    		Z wn(cos(Pi/i),sin(Pi*K/i));
    		for(int j=0;j<n;j+=tmp){
    			Z w(1,0);
    			for(int k=0;k<i;k++,w=w*wn){
    				Z x=a[j+k],y=a[i+j+k]*w;
    				a[j+k]=x+y,a[i+j+k]=x-y;
    			}
    		} 
    	}
    	if(K==-1)for(int i=0;i<n;i++)a[i]/=n;
    }
    
    Z a[N],b[N],c[N];
    string sr;
    int ksm(int x,int k){
    	int ret=1;
    	while(k){
    		if(k&1)ret=(LL)ret*x%mod;
    		x=(LL)x*x%mod,k>>=1;
    	}
    	return ret;
    }
    int ans;
    char now[N];int p[N];
    void Manacher(string s){
    	int len=s.length();
    	for(int i=1;i<=len;i++)now[2*i-1]='%',now[2*i]=s[i-1];
    	now[len=len*2+1]='%';
    	int pos=0,R=0;
    	for (int i=1;i<=len;i++){
    		if(i<R)p[i]=min(p[2*pos-i],R-i); else p[i]=1;
    		while(1<=i-p[i]&&i+p[i]<=len&&now[i-p[i]]==now[i+p[i]]) p[i]++;
    		if(i+p[i]>R)R=i+p[i],pos=i;
    		ans=(ans-p[i]/2+mod)%mod;
    	}
    }
    
    int main(){
    	cin>>sr;
    	int len=sr.length();
    	int x=ceil(log2(len<<1|1));
    	for(int i=0;i<len;i++)a[i].real()=(sr[i]=='a'),b[i].real()=(sr[i]=='a');
    	
    	FFT(a,x,1),FFT(b,x,1);
    	for(int i=0;i<(1<<x);i++)c[i]=a[i]*b[i];
    	fill(a,a+(1<<x),0),fill(b,b+(1<<x),0);
    	for(int i=0;i<len;i++)a[i].real()=(sr[i]=='b'),b[i].real()=(sr[i]=='b');
    	FFT(a,x,1),FFT(b,x,1);
    	for(int i=0;i<(1<<x);i++)c[i]+=a[i]*b[i];
    	
    	FFT(c,x,-1);
    	for(int i=0;i<(1<<x);i+=2)c[i].real()++;
    	
    	for(int i=0;i<(len<<1)-1;i++)ans=(ans+ksm(2,((int)(c[i].real()+0.5))/2)-1)%mod; 
    	Manacher(sr);
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    Numpy学习笔记练习代码 ——(二)
    Requests爬取表格数据并存入CSV中
    Numpy学习练习代码 ——(一)
    Requests爬取中文网站乱码问题
    Pycharm用Ctrl+鼠标滚轮控制字体大小
    一、Windows10下python3和python2同时安装
    inux下配置rsyncd服务
    shell 脚本中$$,$#,$?分别代表什么意思?
    linux shell awk 流程控制语句(if,for,while,do)详细介绍
    定时任务
  • 原文地址:https://www.cnblogs.com/Emiya-wjk/p/10030767.html
Copyright © 2011-2022 走看看