• bzoj3160 万径人踪灭


    正解:$FFT+manacher$。

    这题写得蛋疼。。主要是$manacher$有一个地方写错调了好久。。还有我的计数方法好像跟网上的有点不一样,感觉自己在搞容斥原理一样。。

    我们考虑设$f[i]$为i两边对称的字符对数。例如,$s=aabba$,则$f[3]=1$(下标从1开始)。然后我们发现这个其实很好算。如果$s[i]==s[j]$,那么它必然会对$f[(i+j)/2]$产生贡献。于是我们可以发现,$f[i]=sum_{x+y=i*2}[s[x]==s[y]]$。然后这个肯定是可以用$FFT$跑的,我们对于$a$跑一次$FFT$,对于$b$再跑一次$FFT$。注意整个方案数会多算一次,$i+i=2*i$的情况也会算一次。最终答案就是$Ans=sum_{i=1}^{n}2^{f[i]}-1$,然后再减去连续的子序列。连续的子序列我们用一遍$manacher$算出来就行了,然后又是一波容斥。。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <complex>
     5 #include <cstring>
     6 #include <cstdlib>
     7 #include <cstdio>
     8 #include <vector>
     9 #include <cmath>
    10 #include <queue>
    11 #include <stack>
    12 #include <map>
    13 #include <set>
    14 #define rhl (1000000007)
    15 #define NN (1000010)
    16 #define inf (1<<30)
    17 #define pi acos(-1)
    18 #define il inline
    19 #define RG register
    20 #define ll long long
    21 #define C complex <double>
    22 
    23 using namespace std;
    24 
    25 int p[NN],f[NN],bin[NN],rev[NN],n,nn,N,lg;
    26 char s[NN],c[NN];
    27 C a[NN],b[NN];
    28 ll ans,res;
    29 
    30 il int gi(){
    31     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    32     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    33 }
    34 
    35 il ll manacher(){
    36     RG int id=1,mx=1; RG ll ans=0; p[1]=1;
    37     for (RG int i=2;i<nn;++i){
    38     if (i<mx) p[i]=min(p[(id<<1)-i],mx-i); else p[i]=1;
    39     while (i-p[i]>=0 && s[i+p[i]]==s[i-p[i]]) p[i]++;
    40     if (mx<i+p[i]) mx=i+p[i],id=i;
    41     ans+=(p[i]>>1); if (s[i]!='#') ans--;
    42     }
    43     return ans%rhl;
    44 }
    45 
    46 il void fft(C *a,RG int n,RG int f){
    47     for (RG int i=0;i<n;++i) if (i<rev[i]) swap(a[i],a[rev[i]]);
    48     for (RG int i=1;i<n;i<<=1){
    49     C wn(cos(pi/i),sin(f*pi/i)),x,y;
    50     for (RG int j=0;j<n;j+=(i<<1)){
    51         C w(1,0);
    52         for (RG int k=0;k<i;++k,w*=wn){
    53         x=a[j+k],y=w*a[j+k+i];
    54         a[j+k]=x+y,a[j+k+i]=x-y;
    55         }
    56     }
    57     }
    58     return;
    59 }
    60 
    61 il void work(){
    62     scanf("%s",c+1),n=strlen(c+1); s[0]='#';
    63     for (RG int i=1;i<=n;++i) s[i<<1]='#',s[(i<<1)-1]=c[i];
    64     nn=(n<<1)+1,s[nn]='&'; for (N=1;N<=(nn<<1);N<<=1) lg++;
    65     for (RG int i=0;i<=N;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
    66     for (RG int i=0;i<N;++i) a[i]=s[i]=='a'; fft(a,N,1);
    67     for (RG int i=0;i<N;++i) b[i]=a[i]*a[i],a[i]=s[i]=='b';
    68     fft(a,N,1); for (RG int i=0;i<N;++i) b[i]+=a[i]*a[i]; fft(b,N,-1);
    69     bin[0]=1; for (RG int i=1;i<=nn;++i){ bin[i]=bin[i-1]<<1; if (bin[i]>=rhl) bin[i]-=rhl; }
    70     for (RG int i=1;i<nn;++i){
    71     f[i]=((int)(b[i<<1].real()/N+0.5)-(s[i]!='#'))>>1;
    72     res=bin[f[i]]-1; if (s[i]!='#') ans+=2*res; else ans+=res;
    73     if (ans>=rhl) ans-=rhl;
    74     }
    75     printf("%lld
    ",(ans-manacher()+rhl)%rhl); return;
    76 }
    77 
    78 int main(){
    79     work();
    80     return 0;
    81 }
  • 相关阅读:
    python正则表达式基础,以及pattern.match(),re.match(),pattern.search(),re.search()方法的使用和区别
    python正则表达式--分组、后向引用、前(后)向断言
    python正则表达式--flag修饰符、match对象属性
    mybatis-核心配置文件和mappe.xml
    mybatis mapper标签
    spring JdbcTemplate 常用的自定义工具包
    web基础
    8.24 JDBC 调用存储过程
    8.24 事务处理
    8.24 批处理
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6572513.html
Copyright © 2020-2023  润新知