UVALive 5059 Play with Stones SG函数,难度较低

来源:互联网 发布:专户网络个人投资好吗 编辑:程序博客网 时间:2024/04/30 03:22

题目链接: 见这里
题意: 有n堆石子,分别有a1,a2,”’,an个。两个游戏者轮流操作,每次可以选择一堆,拿走至少石子,但不能拿走超过一半的石子。比如,有3堆石子,每堆分别有5,1,2个,则再下一轮中,游戏者可以从第一堆中拿1个或者2个,第2堆中不能拿,第3堆只能拿一个。谁不能拿石子,谁就输。
解题方法:本题和NIM游戏有些差别,但是也可以看做n个单堆游戏之和。遗憾的是,即是是单堆游戏,由于ai的范围太大,也不能定义递推出所有的sg函数。但是我们可以递推出小范围的sg函数,看看有没有规律:
小范围打表程序如下:

//LA 5059 SG打表#include <stdio.h>#include <string.h>const int maxn = 100;int SG[maxn];int vis[maxn];int main(){    SG[1] = 0;    for(int i = 2; i <= 30; i++){        memset(vis, 0, sizeof(vis));        for(int j = 1; j * 2 <= i; j++) vis[SG[i - j]] = 1;        for(int j = 0; ; j++){            if(!vis[j]){                SG[i] = j;                break;            }        }        printf("%d\n", SG[i]);    }    return 0;}/*1 0 2 1 3 0 4 2 5 1 6 3 7 0 8 4 9 2 10 5 11 1 12 6 13 3 14 7 15当n为偶数时,SG(n) = n/2,但n为奇数时似乎没有什么规律.但是当把n为偶数的值全部删除后得到的数列为0 1 0 2 1 3 0 4 2 5 1 6 3 7*/

所以就开心写出AC代码了

//LA 5059 main.cpp#include <bits/stdc++.h>using namespace std;long long SG(long long x){    return x%2 == 0 ? x / 2 : SG(x / 2);}int main(){    int T; scanf("%d", &T);    while(T--){        int n;        long long a, v = 0;        cin >> n;        for(int i = 0; i < n; i++){            cin >> a;            v ^= SG(a);        }        if(v) puts("YES");        else puts("NO");    }    return 0;}
0 0