• 洛谷P3480 KAM-Pebbles


    题目大意:

    有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数。两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件。谁没有石子可移时输掉游戏。问先手是否必胜。

    要保证序列不下降,这个条件似乎有点困难,于是我们转化一下,令数列(c)为原序列的差分序列,这样每次操作就等价于把(c)中的(c[i],c[i+1])变成(c[i]-x,c[i]+x(x>0))了。然后你需要知道一个叫阶梯Nim游戏的东西。
    阶梯Nim游戏大概就是有(1)(n)(n)个高度递增的台阶,每个台阶上有一些石子,(0)为地面,每次操作可以把一些石子从(i(igeqslant1))移动到(i-1)阶上,不能操作者输(此时所有石子都跑到地面上去了)。
    怎么判断先手是否必胜呢?有如下结论:阶梯Nim游戏等价于所有奇数台阶上石子的Nim游戏。
    可以这样理解:因为我们先手,那就按照Nim游戏的必胜策略在奇数台阶上先操作,然后轮到对手操作了,有下面这两种情况:
    1.他移动偶数台阶上的石子,我们就把他放在奇数台阶上的那一部分石子往下移,这样所有的奇数台阶都没有变
    2.他移动奇数台阶上的石子,我们就继续在奇数台阶上按照必胜策略操作
    经过上面的操作后,剩下的石子一定都在偶数台阶上。假设此时轮到对手操作(我们操作同理),无论他怎么操作,我们都可以把他操作的那一部分石子向下继续移。最后一步(此时能移动的石子都在(1)号台阶上)一定是我们操作,必胜。也就是说最后剩下的那些在偶数台阶上的石子可以忽略不计。
    综上所述,阶梯Nim游戏就等价于在奇数台阶上操作的Nim游戏。

    看原题,不就是一个倒过来的阶梯Nim游戏吗?倒着扫一遍就好了!
    代码:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define N 1000
    
    int T, n, a[N+5], c[N+5];
    
    int main() {
        scanf("%d", &T);
        while(T--) {
            scanf("%d", &n);
            for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), c[i] = a[i]-a[i-1];
            int ans = 0;
            for(int i = n; i >= 1; i -= 2) ans ^= c[i];
            if(ans) printf("TAK
    ");
            else printf("NIE
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    《人件》阅读笔记五
    《人件》阅读笔记四
    《人件》阅读笔记三
    《人件》阅读笔记二
    《人件》阅读笔记一
    年报系统课堂讨论记录
    系统利益相关者描述案例
    Android开发学习记录--活动生命周期
    jQuery AJAX简介
    jQuery HTML简介
  • 原文地址:https://www.cnblogs.com/dummyummy/p/10137752.html
Copyright © 2020-2023  润新知