zoukankan      html  css  js  c++  java
  • [PKUSC2018]神仙的游戏 题解

    [PKUSC2018]神仙的游戏 题解

    Problem

    ​ 小D和小H发现了一种新的游戏。

    ​ 给出一个由0/1/?组成的字符串 (s) ,将 (s) 中的问号用0/1替换,对每个 (l) 口算是否存在替换问号的方案使得 (s) 长度为 (l) 的前缀成为border,把这个结果记做 (f(l)=0/1)

    请计算 ((f(1) imes 1^2) otimes (f(2) imes 2^2) otimes cdots otimes (f(n) imes n^2))

    (|s| leq 5 imes 10^5)

    Solution

    对于一个长度为 (len) 的border,必定会有 (s_{i}=s_{n-len+i})

    我们可以得到一个这样的性质:若任取 (i equiv j (mod x)) ,都有 (s_i=s_j) ,则 (n-x) 是一个border。

    所以,倘若 (i equiv j (mod x))(s_i eq s_j) ,则 (n-x) 必定不是一个border。即只要知道有一对01的差是 (d) ,就一定会有对于一个 ((n-len)|d)(len) 都不是一个border。

    所以我们只要求出两两01的差,就能判断border,而这个只要FFT即可。

    Code

    #include<bits/stdc++.h>
    #define DB double
    #define LL long long
    using namespace std;
    
    const DB Pi=acos(-1);
    
    LL n,Ans;
    char s[500005];
    int vis[500005],rev[2000005];
    
    struct Complex{
    
        DB x,y;
    
        inline Complex operator + (const Complex &A)const{
            return (Complex){x+A.x,y+A.y};
        }
    
        inline Complex operator - (const Complex &A)const{
            return (Complex){x-A.x,y-A.y};
        }
    
        inline Complex operator * (const Complex &A)const{
            return (Complex){x*A.x-y*A.y,x*A.y+y*A.x};
        }
    
    }F[2000005],G[2000005];
    
    void FFT(Complex *F,int Lim,int op){
        for(register int i=0;i<Lim;++i){
            if(i<rev[i])
                swap(F[i],F[rev[i]]);
        }
        for(register int mid=1;mid<Lim;mid<<=1){
            int R=mid<<1;
            Complex rt=(Complex){cos(Pi/mid),op*sin(Pi/mid)};
            for(register int j=0;j<Lim;j+=R){
                Complex w=(Complex){1,0};
                for(register int k=0;k<mid;++k){
                    Complex x=F[j|k],y=w*F[j|k|mid];
                    F[j|k|mid]=x-y;
                    F[j|k]=x+y;
                    w=w*rt;
                }
            }
        }
        if(op==-1){
            for(register int i=0;i<Lim;++i){
                F[i].x/=Lim;
                F[i].y/=Lim;
            }
        }
        return;
    }
    
    int main(){
        
        scanf("%s",s+1);n=strlen(s+1);
    
        int Lim=1,Len=-1;
        while(Lim<(n+1<<1))
            Lim<<=1,++Len;
        for(register int i=0;i<Lim;++i)
            rev[i]=(rev[i>>1]>>1)|((i&1)<<Len);
    
        for(register int i=0;i<n;++i)
            F[i].x=(s[i+1]=='0');
    
        for(register int i=0;i<n;++i)
            G[i].x=(s[n-i]=='1');
    
        FFT(F,Lim,+1);FFT(G,Lim,+1);
        for(register int i=0;i<Lim;++i)
            F[i]=F[i]*G[i];
        FFT(F,Lim,-1);
    
        for(register int i=1;i<(n<<1);++i)
            vis[abs(i-n+1)]+=(F[i].x+0.5);
    
        for(register int i=1;i<n;++i){
            int flag=1;
            for(register int j=1;i*j<=n;++j){
                if(vis[i*j]){
                    flag=0;
                    break;
                }
            }
            if(flag)
                Ans^=1LL*(n-i)*(n-i);
        }
    
        printf("%lld
    ",Ans^(1LL*n*n));
    
        return 0;
    }
    
  • 相关阅读:
    scrapy中selenium的应用
    Django的锁和事务
    redis
    【leetcode】187. Repeated DNA Sequences
    【leetcode】688. Knight Probability in Chessboard
    【leetcode】576. Out of Boundary Paths
    【leetcode】947. Most Stones Removed with Same Row or Column
    【leetcode】948. Bag of Tokens
    【leetcode】946. Validate Stack Sequences
    【leetcode】945. Minimum Increment to Make Array Unique
  • 原文地址:https://www.cnblogs.com/zjy123456/p/13836474.html
Copyright © 2011-2022 走看看