zoukankan      html  css  js  c++  java
  • BZOJ 3160 万径人踪灭

    Description

    Input

    Output

     

    Sample Input

     

    Sample Output

     

    HINT

    先在串中两两之间插入#,形成新串s,主要是考虑中心不在列上
    令$f[i]$表示以i为中心,两边为a或b且相同的对数
    $f[i]=sum_{x+y=i*2}[s[x]==s[y]]$
    注意$s[x]s[y]$不能为#
    发现这其实是一个卷积,于是FFT,求出f[i]
    于是通过f[i]算出答案
    $Ans=sum_{i=1}^{n}2^{f[i]}-1$
    因为不能连续,减去连续的回文串数,用manacher
    但有几个细节:
    每对(x,y)其实等价于(y,x),所以要除2
    然而当s[i]不是#,实际上因为$i+i=2×i$
    只算了一次,当s[i]不是#时,f[i]要-1再除2再+1
    如果s[i]是#就直接除2

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 #include<complex>
      7 using namespace std;
      8 typedef complex<double> dob;
      9 typedef long long lol;
     10 double pi=acos(-1.0);
     11 const int NN=1000000;
     12 int Mod=1000000007;
     13 dob a[NN],b[NN];
     14 int lg,R[NN],n,tot,N,f[NN],pw[NN];
     15 lol ans;
     16 char ch[NN],s[NN];
     17 int qpow(int x,int y)
     18 {
     19   int res=1;
     20   while (y)
     21     {
     22       if (y&1) res=1ll*res*x%Mod;
     23       x=1ll*x*x%Mod;
     24       y>>=1;
     25     }
     26   return res;
     27 }
     28 void FFT(dob *A,int len,double o)
     29 {int i,j,k;
     30   for (i=0;i<len;i++)
     31     if (i<R[i]) swap(A[i],A[R[i]]);
     32   for (i=1;i<len;i<<=1)
     33     {
     34       dob wn(cos(pi/i),sin(o*pi/i)),x,y;
     35       for (j=0;j<len;j+=(i<<1))
     36     {
     37       dob w(1,0);
     38       for (k=0;k<i;k++,w*=wn)
     39         {
     40           x=A[j+k];y=w*A[j+k+i];
     41           A[j+k]=x+y;
     42           A[j+k+i]=x-y;
     43         }
     44     }
     45     }
     46 }
     47 lol manacher()
     48 {lol i,len[800001];
     49   lol mx=0,po=0;
     50   lol as=0;
     51   for (i=1;i<N;i++)
     52     {
     53       if (mx>i)
     54     len[i]=min(mx-i,len[2*po-i]);
     55       else len[i]=1;
     56       while (i-len[i]>=0&&i+len[i]<=N&&s[i-len[i]]==s[i+len[i]]) len[i]++;
     57       if (len[i]+i>mx)
     58     {
     59       po=i;
     60       mx=len[i]+i;
     61     }
     62       if (s[i]!='#') as+=(len[i]-1)/2+1;
     63       else as+=(len[i]-1)/2;
     64       as%=Mod;
     65     }
     66   return as;
     67 }
     68 int main()
     69 {int i,len;
     70   scanf("%s",ch);
     71   n=strlen(ch);
     72   tot=-1;
     73   for (i=0;i<n;i++)
     74     {
     75       s[++tot]='#';
     76       s[++tot]=ch[i];
     77     }
     78   s[++tot]='#';s[++tot]='$';
     79   N=tot;
     80   len=1;
     81   while (len<=2*N) len*=2,lg++;
     82   for (i=0;i<len;i++)
     83     R[i]=(R[i>>1]>>1)|((i&1)<<(lg-1));
     84   for (i=0;i<len;i++)
     85     a[i]=(double)(s[i]=='a');
     86   FFT(a,len,1);
     87   for (i=0;i<len;i++)
     88     b[i]=a[i]*a[i];
     89   for (i=0;i<len;i++)
     90     a[i]=(double)(s[i]=='b');
     91   FFT(a,len,1);
     92   for (i=0;i<len;i++)
     93     b[i]+=a[i]*a[i];
     94   FFT(b,len,-1);
     95   for (i=0;i<N;i++)
     96     f[i]=((int)(b[i*2].real()/(double)len+0.5)-(s[i]!='#'))>>1;
     97   pw[0]=1;
     98   for (i=1;i<=n;i++)
     99     pw[i]=pw[i-1]*2%Mod;
    100   for (i=1;i<N;i++)
    101     {
    102       lol res=pw[f[i]]-1;
    103       if (s[i]!='#') res=res*2%Mod+1;
    104       ans+=res;
    105       if (ans>=Mod) ans-=Mod;
    106     }
    107   printf("%lld
    ",(ans-manacher()+Mod)%Mod);
    108 }
  • 相关阅读:
    《jQuery实战(第二版)》读书笔记
    软件测试对于代码安全的诸多事宜
    关于Maven的安装及初步使用
    Windows下GIT安装与使用(上传远程端)
    白盒测试
    关于VS2013的编码的UI测试。
    闰年检验
    等价类划分例子中的些许添加
    软件测试技术第二周课堂等价类习题
    软件测试技术第一周课堂随笔记录
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8385186.html
Copyright © 2011-2022 走看看