zoukankan      html  css  js  c++  java
  • loj 6436 PKUSC2018 神仙的游戏

    传送门

    好妙蛙

    即串(s)长度为(n)首先考虑如果一个长度为(len)(border)存在,当且仅当对所有(iin[1,len],s[i]=s[n-len+i]),也就是所有模(n-len)同余的所有位置上的字符要相同,如果存在一对(0,1),他们之间的下标之差为(x),则对于所有的(y|x),长度为(n-y)(border)不存在

    所以暴力做法是枚举所有确定的(0,1)对,然后把所有得到的长度以及这些长度的因数全部标记,利用质因数分解统计答案可以做到(O(nlogn))

    现在考虑优化前面的枚举部分,搞两个生成函数(A(x)=sum_{i=0}^{n-1}[s_i=0]x^i,B(x)=sum_{i=0}^{n-1}[s_{n-i-1}=1]x^i),如果把他们(FFT)起来,得到的(C(x))(C_k=sum_{j=0}^{k}A_jB_{k-j}=sum_{j=0}^{k}[s_j=0][s_{n-k-1+j}=1]x^k),这第(k)项的系数也就是下标之差为(|n-k-1|)的(0,1)对数量

    然后就可以(O(nlogn))加大常数完成此题

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define db double
    #define il inline
    #define re register
    #define eps (1e-5)
      
    using namespace std;
    const int N=500000+10,M=1050000+10;
    const db pi=acos(-1);
    il int rd()
    {
      int x=0,w=1;char ch=0;
      while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
      return x*w;
    }
    struct comp
    {
      db r,i;
      comp(){r=i=0;}
      comp(db nr,db ni){r=nr,i=ni;}
      il comp operator + (const comp &bb) const {return comp(r+bb.r,i+bb.i);}
      il comp operator - (const comp &bb) const {return comp(r-bb.r,i-bb.i);}
      il comp operator * (const comp &bb) const {return comp(r*bb.r-i*bb.i,r*bb.i+i*bb.r);}
    }a[M],b[M];
    int n,m,nn,l,rdr[M];
    il void fft(comp *a,int op)
    {
      comp W,w,x,y;
      for(int i=0;i<nn;++i) if(i<rdr[i]) swap(a[i],a[rdr[i]]);
      for(int i=1;i<nn;i<<=1)
        {
          W=comp(cos(pi/i),op*sin(pi/i));
          for(int j=0;j<nn;j+=i<<1)
            {
              w=comp(1,0);
              for(int k=0;k<i;++k,w=w*W)
                {
                  x=a[j+k],y=w*a[j+k+i];
                  a[j+k]=x+y,a[j+k+i]=x-y;
                }
            }
        }
    }
    char cc[N];
    bool no[N];
    int prm[N],tt,pp[N];
    
    int main()
    {
      scanf("%s",cc);
      n=strlen(cc);
      m=n+n;
      for(nn=1;nn<=m;nn<<=1) ++l;
      for(int i=0;i<nn;++i) rdr[i]=(rdr[i>>1]>>1)|((i&1)<<(l-1));
      for(int i=0;i<n;++i) a[i].r=(cc[i]=='0'),b[i].r=(cc[n-i-1]=='1');
      fft(a,1),fft(b,1);
      for(int i=0;i<nn;++i) a[i]=a[i]*b[i];
      fft(a,-1);
      for(int i=0;i<n;++i) no[i]=(fabs(a[n-1-i].r)/nn>eps||fabs(a[n-1+i].r)/nn>eps);
      for(int i=2;i<=n;++i)
        {
          if(!pp[i]) pp[i]=i,prm[++tt]=i;
          for(int j=1;j<=tt&&i*prm[j]<=n;++j)
            {
              pp[i*prm[j]]=prm[j];
              if(i%prm[j]==0) break;
            }
        }
      for(int i=n-1;i>=1;--i)
        {
          int x=i;
          while(x>1) no[i/pp[x]]|=no[i],x/=pp[x];
        }
      LL ans=0;
      for(int i=1;i<=n;++i) ans^=1ll*(no[n-i]^1)*i*i;
      printf("%lld
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    GUI编程笔记(java)02:java.awt和java.swing包的区别
    GUI编程笔记(java)01:GUI和CLI
    Android(java)学习笔记138:三重for循环的优化(Java面试题)
    Android(java)学习笔记137:ListView编写步骤(重点)
    Android(java)学习笔记136:利用谷歌API对数据库增删改查(推荐使用)
    Android(java)学习笔记135:SQLite数据库(表)的创建 以及 SQLite数据库的升级
    spring ioc 注解配置
    代码简洁之道与重构
    快速定位到方法的被调用处
    spring ioc xml配置
  • 原文地址:https://www.cnblogs.com/smyjr/p/10081119.html
Copyright © 2011-2022 走看看