• LuoguP5652 基础博弈练习题 博弈


    归纳+找规律.    

    如果终点 $r$ 是奇数,那么 $r-m-1$ ~ $r-1$ 这段区间都是先手必败.      

    然后我们发现 $r-m-1$ 及之前都是偶数的话还是先手比败,直到遇到一个奇数,就又变成了先手必胜.  

    那么,对于一个奇数位置,其前面第一个先手必胜位置就是 $r-m-1$ 前第一个奇数位置.   

    对于偶数,我们发现是先手必败,而其前面第一个先手必胜点就是其前面第一个奇数点.    

    上述关系构成了一个树形结构,即偶数的话让前面第一个奇数连它,奇数的话让 $i-m-1$ 之前第一个奇数连它.     

    如果 $[l,r]$ 满足先手必胜,则要求 $l$ 在树上是 $r$ 的祖先,这个用 DFS 序判断一下就行了.   

    code:  

    #include <bits/stdc++.h>           
    #define N 1000009   
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin)  
    using namespace std;  
    int n,m,q,type,deco[5],edges,tim;
    int a[N],fa[N],hd[N],to[N],nex[N],st[N],ed[N];  
    void add(int u,int v) { 
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;   
    }
    void dfs(int x) {     
        st[x]=++tim;   
        for(int i=hd[x];i;i=nex[i]) 
            dfs(to[i]);  
        ed[x]=tim;    
    }
    int RAN() {  
        return deco[0]=(deco[0]*deco[1]+deco[2])%deco[3];                               
    }
    void get(int &x,int &y) {  
        if(type==0) scanf("%d%d",&x,&y);   
        else {    
            x=RAN()%n+1,y=RAN()%n+1;  
            if(x>y) swap(x,y);   
        }
    }
    int main() {  
        // setIO("input");    
        scanf("%d%d%d%d",&n,&m,&q,&type);                      
        for(int i=1;i<=n;++i) {
            scanf("%d",&a[i]);   
            if(a[i]&1) {     
                if(i-m-1>0) {
                    if(a[i-m-1]&1) fa[i]=i-m-1; 
                    else fa[i]=fa[i-m-1];   
                }     
            }
            else {      
                if(a[i-1]&1) fa[i]=i-1;    
                else fa[i]=fa[i-1];   
            }
        }      
        if(type==1) {
            for(int i=0;i<4;++i) scanf("%d",&deco[i]);   
        }
        for(int i=1;i<=n;++i) add(fa[i],i);  
        dfs(0);    
        int x,y,z;      
        ll ans=0;  
        ll mod=1ll<<32;  
        for(int i=1;i<=q;++i) {   
            get(x,y);      
            if(x==y) {  
                if(a[x]%2==0) 
                    (ans+=(ll)i*i%mod)%=mod;  
                continue;  
            }
            if(st[y]>=st[x]&&st[y]<=ed[x]) {      
                continue;  
            }       
            (ans+=(ll)i*i%mod)%=mod;  
        }    
        printf("%lld
    ",ans);   
        return 0; 
    }
    

      

  • 相关阅读:
    增加samba用户提示Failed to add entry for user
    二叉树
    excel技巧
    mongodb导入json文件
    mongodb导出数据csv格式
    mongoexport导出csv中文乱码
    左连接,结果大于左面的表验证 解释
    plsql 用法和技巧
    对javaNI和NIO理解
    TinyMCE4.x整合教程-Xproer.WordPaster
  • 原文地址:https://www.cnblogs.com/guangheli/p/13283549.html
Copyright © 2020-2023  润新知