zoukankan      html  css  js  c++  java
  • [bzoj3160] 万径人踪灭

    Description

    img

    img

    Input

    img

    Solution

    考虑先忽略不可以连成一段的条件。

    那么,暴力的做法就是,枚举一个中心点,暴力找出旁边有多少个对称的点,设数量为(x),则这个中心点对答案的贡献为(2^x-1)

    这样是(O(n^2))的,考虑怎么优化。

    对于中心点(mid),能对(x)造成贡献的位置(i,j),一定是满足(i+j=mid*2)(s[i]=s[j])

    写出来就是:

    [ans=sum_{i=1}^{mid-1}[s_i=s_{mid*2-i}] ]

    然后可以发现这其实是一个卷积的形式,那么弄两个多项式(A,B)出来,(A_i=[s[i]=a])(B_i=[s[i]=b])

    然后分别自乘,(mid)处的答案就是:

    [2^{A_{mid}+B_{mid}}-1 ]

    然后细节注意下就好了。

    然后考虑怎么处理连成一段的,这部分要减去。

    这个实质上就是原串回文串的个数,跑一边(manacher)就好了。

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 1e6+10;
    const int mod = 998244353;
    const int MOD = 1e9+7;
    
    char c[maxn],s[maxn];
    int n,a[maxn],b[maxn],f[maxn];
    int N,bit,pos[maxn];
    
    int qpow(int A,int x,int p) {
    	int res=1;
    	for(;x;x>>=1,A=1ll*A*A%p) if(x&1) res=1ll*res*A%p;
    	return res;
    }
    
    void ntt(int *r,int op) {
    	for(int i=0;i<N;i++) if(pos[i]>i) swap(r[i],r[pos[i]]);
    	for(int i=1;i<N;i<<=1) {
    		int wn=qpow(op==1?3:qpow(3,mod-2,mod),(mod-1)/(i<<1),mod);
    		for(int j=0;j<N;j+=(i<<1))
    			for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod) {
    				int x=r[j+k],y=1ll*w*r[i+j+k]%mod;
    				r[j+k]=(x+y)%mod,r[i+j+k]=(x-y+mod)%mod;
    			}
    	}
    	if(op==-1) {
    		int inv=qpow(N,mod-2,mod);
    		for(int i=0;i<N;i++) r[i]=1ll*r[i]*inv%mod;
    	}
    }
    
    int manacher() {
    	int res=0,cnt=0;s[cnt]='$',s[++cnt]='%';
    	for(int i=1;i<=n;i++) s[++cnt]=c[i],s[++cnt]='%';
    	int mid=1,mr=1;
    	for(int i=1;i<=cnt;i++) {
    		f[i]=min(mr-i,f[mid*2-i]);
    		while(s[i+f[i]]==s[i-f[i]]) f[i]++;
    		if(i+f[i]>mr) mr=i+f[i],mid=i;
    		res=(res+f[i]/2)%MOD;
    	}
    	return res;
    }
    
    int main() {
    	scanf("%s",c+1);n=strlen(c+1);
    	for(int i=1;i<=n;i++) if(c[i]=='a') a[i]=1;else b[i]=1;
    	N=1,bit=0;while(N<=(n<<1)) N<<=1,bit++;
    	for(int i=0;i<N;i++) pos[i]=pos[i>>1]>>1|((i&1)<<(bit-1));
    	ntt(a,1),ntt(b,1);
    	for(int i=0;i<N;i++) a[i]=1ll*a[i]*a[i]%mod,b[i]=1ll*b[i]*b[i]%mod;
    	ntt(a,-1),ntt(b,-1);int ans=0;
    	for(int i=2;i<=n*2;i++) {
    		if(!(i&1)) {if(c[i>>1]=='a') a[i]++;else b[i]++;}
    		a[i]>>=1,b[i]>>=1;
    		ans=(ans+qpow(2,a[i]+b[i],MOD)-1)%MOD;
    	}
    	ans=(ans-manacher()+MOD)%MOD;
    	write((ans+MOD)%MOD);
    	return 0;
    }
    
  • 相关阅读:
    微信js sdk动态引用
    mysql
    github 常用
    使用Win32DiskImager后重置SD卡
    nuxt generate静态化后回退问题
    nuxt.config有关router配置
    vue本人常用插件汇总(常更新)
    Windows Server 2008 IIS 并发请求设置
    Python 高级编程 ——观察者模式
    MYSQL语句大全
  • 原文地址:https://www.cnblogs.com/hbyer/p/10329360.html
Copyright © 2011-2022 走看看