zoukankan      html  css  js  c++  java
  • 「PKUSC2018」神仙的游戏

    题目链接:Click here

    Solution:

    这道题感觉还是不太难的。。。

    考虑若存在一个长度为(len)(border),那么对于(forall iin [1,len])都有(s[i]=s[n-len+i])

    注意到下标之间的差值为(n-len),也就是说,所有下标差为(n-len)的位置必须相同

    这里的相同包括某一个是(?)的情况,也就是说(?)其实是没有影响的

    有了上面的条件,我们可以发现若有一对((0,1))的位置相差(l),那么对于所有的(x|l),都不存在长度为(n-x)(border)

    我们已经知道本题的关键就是((0,1))对了,那么如何来找呢?

    考虑构造两个生成函数(A(x),B(x))

    [A(x)=sum_{i=0}^{n-1} x^i[s_i=0]\ B(x)=sum_{i=0}^{n-1} x^i[s_i=1]\ ]

    我们知道卷积的形式就是指数相加,和为定值,那么我们现在要的是差为定值,那么把其中一个生成函数(reverse)即可

    现在我们得到了新的(C(x)=A(x)B(x))(C(x))的第(i)系数即为下标差为(i-n)((0,1))对数

    最后我们再枚举下标差即可,时间复杂度(O(n log n))

    Code:

    #include<bits/stdc++.h>
    #define Pi acos(-1.0)
    #define int long long 
    using namespace std;
    const int N=2e6+10;
    const double eps=1e-3;
    char s[N];
    int n,ans,len=1,tim,rtt[N],f[N];
    struct cp{double x,y;}A[N*2],B[N];
    cp operator + (cp a,cp b){return (cp){a.x+b.x,a.y+b.y};}
    cp operator - (cp a,cp b){return (cp){a.x-b.x,a.y-b.y};}
    cp operator * (cp a,cp b){return (cp){a.x*b.x-a.y*b.y,a.y*b.x+a.x*b.y};}
    void FFT(cp *a,int flag){
        for(int i=0;i<len;i++)
            if(i<rtt[i]) swap(a[i],a[rtt[i]]);
        for(int l=2;l<=len;l<<=1){
            cp wn=(cp){cos(flag*2*Pi/l),sin(flag*2*Pi/l)};
            for(int st=0;st<len;st+=l){
                cp w=(cp){1,0};
                for(int u=st;u<st+(l>>1);u++,w=w*wn){
                    cp x=a[u],y=w*a[u+(l>>1)];
                    a[u]=x+y,a[u+(l>>1)]=x-y;
                }
            }
        }
    }
    signed main(){
        scanf("%s",s);n=strlen(s);
        while(len<=(2*n)) len<<=1,++tim;
        for(int i=0;i<len;i++)
            rtt[i]=(rtt[i>>1]>>1)|((i&1)<<(tim-1));
        for(int i=0;i<n;i++){
            A[i].x=(s[i]=='1');
            B[n-i-1].x=(s[i]=='0');
        }
        FFT(A,1);FFT(B,1);
        for(int i=0;i<=len;i++) A[i]=A[i]*B[i];
        FFT(A,-1);for(int i=0;i<=len;i++) A[i].x=(A[i].x)/len;
        for(int i=n-1;i;i--)
            if(A[n-1+i].x+A[n-1-i].x>eps) f[i]=1;
        for(int i=1;i<n;i++){
            int flag=1;
            for(int j=1;j*i<=n;j++)
                if(f[j*i]){flag=0;break;}
            if(flag) ans=ans^((n-i)*1ll*(n-i));
        }ans^=(n*1ll*n);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    cookie写入,读取,删除
    javascript模板
    javascript思维导图
    html+css
    Google Java编程风格指南
    mysql1449 The user specified as a definer ('root'@'%') does not exist 解决方法
    mongoDB非正常关闭后无法启动问题
    Android应用程序注册广播接收器(registerReceiver)的过程分析
    Android应用程序在新的进程中启动新的Activity的方法和过程分析
    Android系统中的广播(Broadcast)机制简要介绍和学习计划
  • 原文地址:https://www.cnblogs.com/NLDQY/p/12238445.html
Copyright © 2011-2022 走看看