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

    题意:

    在一个仅含有$a,b$的字符串里选取一个子序列,使得:

    1.位置和字符都关于某条对称轴对称;

    2.不能是连续的一段。

    题解:

    很久以前写的题解太扯淡了。。重新写一篇

    首先对于限制$2$我们可以把它转化成没有限制-连续回文子串

    然后我们发现问题等价于枚举对称轴然后求有几个位置关于它对称

    至今不会manacher于是用hash(哪有题目会卡这个log的

    暴力是$n^2$的 和位置有关的匹配考虑一下$FFT$

    两个位置关于$i$对称的话,一个是i-k,一个是i+k

    发现他们的下标和是2*i

    这说明了我们只需要自己卷自己就好了

    如何卷呢,我们要保证$aa=1,bb=1,ab=ba=0$

    令a的位置权值为0,b的位置权值为1

    直接算相同地方式子会比较复杂$({(a[x]-a[y])}^2-1)^2$

    我们可以容斥一下算不同的,那么就是$(a[x]-a[y])^2$

    展开一下套fft就可以了

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define me(x) memset(x,0,sizoef(x))
    #define mep(x,y) memcpy(x,y,sizeof(y))
    #define ll long long
    #define mid ((h+t+1)>>1)
    #define ull unsigned ll
    namespace IO{
        char ss[1<<24],*A=ss,*B=ss;
        IL char gc()
        {
            return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
        }
        template<class T>IL void read(T &x)
        {
            rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
            while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); 
        }
        char sr[1<<24],z[20]; int Z,C=-1;
        template<class T>IL void wer(T x)
        {
            if (x<0) sr[++C]='-',x=-x;
            while (z[++Z]=x%10+48,x/=10);
            while (sr[++C]=z[Z],--Z);
        }
        IL void wer1() {sr[++C]=' ';}
        IL void wer2() {sr[++C]='
    ';}
        template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
        template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
        template<class T>IL T MAX(T x,T y) {return x>y?x:y;}
        template<class T>IL T MIN(T x,T y) {return x<y?x:y;} 
    };
    using namespace IO;
    const int N=6e5;
    const int mo=1e9+7;
    const double pi=acos(-1);
    struct cp{
        double x,y;
        cp operator + (const cp o) const
        {
            return (cp){o.x+x,o.y+y};
        }
        cp operator - (const cp o) const
        {
            return (cp){x-o.x,y-o.y};
        }
        cp operator * (const cp o) const
        {
            return (cp){x*o.x-y*o.y,x*o.y+y*o.x};
        }
    }w[N],a[N],b[N];
    char s[N];
    int t[N],n,m,A1[N],B1[N],sum[N],jl[N];
    ull jd[N],hash1[N],hash2[N];
    IL int fsp(int x,int y)
    {
        ll ans=1;
        while (y)
        {
            if (y&1) ans=ans*x%mo;
            x=1ll*x*x%mo; y>>=1;
        }
        return ans;
    }
    IL bool check(int x1,int y1,int x2,int y2)
    {
        if ((hash1[y1]-hash1[x1-1])*jd[n-x1]==(hash2[x2]-hash2[y2+1])*jd[y2-1])
           return(1); else return(0);    
    }
    int l,r[N];
    void fft_init()
    {
        l=0; for (n=1;n<=m;n<<=1) l++;
        for (int i=0;i<n;i++) r[i]=(r[i/2]/2)|((i&1)<<(l-1));
        for (int i=0;i<n;i++) w[i]=(cp){cos(pi*i/n),sin(pi*i/n)};
    }
    void fft_clear()
    {
        rep(i,0,n) a[i].x=a[i].y=b[i].x=b[i].y=0;
    }
    void fft(cp *a,int o)
    {
        for (int i=0;i<n;i++) if (i>r[i]) swap(a[i],a[r[i]]);
        for (int i=1;i<n;i<<=1)
          for (int j=0;j<n;j+=(i*2))
            for (int k=0;k<i;k++)
            {
                cp W=w[n/i*k]; W.y*=o;
                cp x=a[j+k],y=a[i+j+k]*W;
                a[j+k]=x+y; a[i+j+k]=x-y;
            }
        if (o==-1) rep(i,0,n-1) a[i].x/=n;
    }
    IL void get_cj(int *A,int *B,int len)
    {
        m=2*len;
        fft_init();
        rep(i,0,len) a[i].x=A[i],b[i].x=B[i];
        fft(a,1); fft(b,1);
        rep(i,0,n) a[i]=a[i]*b[i];
        fft(a,-1);
        rep(i,0,m) B[i]=(int)(a[i].x+0.5);
        fft_clear();
    }
    int main()
    {
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
        cin>>s;
        n=strlen(s);
        rep(i,1,n) t[i]=s[i-1]-'a',sum[i]=sum[i-1]+t[i];
        jd[0]=1;
        rep(i,1,n) jd[i]=jd[i-1]*3;
        rep(i,1,n) hash1[i]=hash1[i-1]+(t[i]+1)*jd[i];
        dep(i,n,1) hash2[i]=hash2[i+1]+(t[i]+1)*jd[n-i+1];
        ll ans=0;
        rep(i,1,n)
        {
            int h=0,t=MIN(n-i,i-1);
            while(h<t)
            {
                if (check(i-mid,i,i,i+mid)) h=mid;
                else t=mid-1;
            }
            ans-=h+1;
        }
        rep(i,1,n-1)
        {
            int h=0,t=MIN(n-i,i)-1;
            while (h<t)
            {
                if (check(i-mid,i,i+1,i+1+mid)) h=mid;
                else t=mid-1;
            }
            if (check(i,i,i+1,i+1)) ans-=h+1;
        }
        rep(i,1,2*n)
        {
          if (i<=n) jl[i]=(i/2)-sum[i-1];
          else jl[i]=((2*n-i+2)/2)-(sum[n]-sum[i-n-1]);
          if ((i&1)==0) jl[i]-=t[i/2];
        }
        rep(i,0,n-1) A1[i]=t[i+1],B1[i]=t[i+1]; 
        get_cj(A1,B1,n);
        dep(i,2*n,2) B1[i]=B1[i-2];
        rep(i,1,2*n) if (i%2==0) B1[i]+=t[i/2];
        rep(i,2,2*n) jl[i]+=B1[i];
        rep(i,1,2*n) (ans+=fsp(2,jl[i])-1)%=mo;
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    xfce4-windowck-plugin的替代品
    git使用Beyond Compare作为diff和merge工具
    Visual Studio设置多个快捷键
    scrapy参数-COOKIES_ENABLED 最权威解释, 帮你避坑
    Linux基础使用
    python 所有的库整理
    Nginx配置详解
    15个常用的javaScript正则表达式
    Redis开发建议
    mysql 同步大量数据小技巧
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8196596.html
Copyright © 2011-2022 走看看