zoukankan      html  css  js  c++  java
  • [HDU5996]dingyeye loves stones

    题目

    点这里看题目。

    分析

    不难想到,这个问题实际上可以按照深度来划分(根的深度为 0),于是这就是一个阶梯 Nim 的问题。

    阶梯 Nim 相当经典,它的模型是:

    (n) 堆石子,编号为 (1sim n),第 (i) 堆有 (a_i) 个石子( (a_i>0) )。每一轮玩家可以选择任意非空的一堆 (k) ,并且可以移动任意多且不为零的石子至 (k-1) 堆(移动第 1 堆的石子相当于直接丢掉它们)。请问先手是否必胜?

    问题的结论是:

    阶梯 Nim 等价于对奇数堆的石子做 Nim 游戏。

    考虑这样的过程:

    1. 如果对手移动奇数堆的石子,我们就按照 Nim 的策略来移动。这样每次操作后,奇数堆的石子会移动到偶数堆里面,奇数堆就是正常的 Nim 过程。
    2. 如果对手不按常理出牌,移动了偶数堆(第 (2n) 堆)的 (k) 个石子。那么我们就可以在 (2n-1) 堆里面,移动恰好 (k) 个石子至第 (2n-2) 堆。最后,要么这 (k) 个石子被丢掉,要么 (k) 个石子移动到偶数堆里,这样奇数堆的石子照样不会被影响。

    这就是阶梯 Nim 的解决方案。实际上,这个结论是告诉我们,阶梯 Nim 的 SG 和是各个奇数位置的堆的异或和

    回到原题。我们认为根的深度是 0 ,看做是 "垃圾桶" (也就是石子丢弃的位置)。对于同一深度上石子堆,移动它们的过程就相当于 Nim 的过程,于是某一深度的 SG 值就是该层上的石子的异或和;对于不同的深度,我们可以将它们看成是阶梯 Nim 的问题,于是整个游戏的 SG 值就是奇数深度的 SG 值的异或值。

    代码:

    #include <cstdio>
    
    const int MAXN = 1e5 + 5;
    
    template<typename _T>
    void read( _T &x )
    {
        x = 0;char s = getchar();int f = 1;
        while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
        while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
        x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
        if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
        if( 9 < x ){ write( x / 10 ); }
        putchar( x % 10 + '0' );
    }
    
    struct Edge
    {
        int to, nxt;
    }Graph[MAXN << 1];
    
    int dep[MAXN];
    int head[MAXN], num[MAXN];
    int N, cnt, Nim;
    
    void AddEdge( const int from, const int to )
    {
        Graph[++ cnt].to = to, Graph[cnt].nxt = head[from];
        head[from] = cnt;
    }
    
    void DFS( const int u, const int fa )
    {
        if( ( dep[u] = dep[fa] + 1 ) % 2 == 0 ) Nim ^= num[u];
        for( int i = head[u] ; i ; i = Graph[i].nxt )
            DFS( Graph[i].to, u );
    }
    
    void Clean()
    {
        Nim = cnt = 0;
        for( int i = 0 ; i <= N ; i ++ )
            head[i] = dep[i] = num[i] = 0;
    }
    
    int main()
    {
        int T;
        read( T );
        while( T -- )
        {
            read( N ), Clean();
            for( int i = 1, fa ; i < N ; i ++ ) read( fa ), AddEdge( fa, i );
            for( int i = 0 ; i < N ; i ++ ) read( num[i] );
            DFS( 0, 0 );
            
            puts( Nim ? "win" : "lose" );
        }
        return 0;
    }
    
  • 相关阅读:
    从运维角度浅谈 MySQL 数据库优化
    好的架构不是设计出来的,而是演进出来的
    京东咚咚架构演进
    大型网站的架构
    MySQL开发规范
    MySQL 5.6的72个新特性(译)
    MySQL数据库运维的五大指标
    MySQL5.0、5.1、5.5、5.6功能进化
    MySQL各版本的区别
    ajax该什么时候用
  • 原文地址:https://www.cnblogs.com/crashed/p/13746175.html
Copyright © 2011-2022 走看看