HDOJ 3537 Daizhenyang's Coin

来源:互联网 发布:淘宝买号 编辑:程序博客网 时间:2024/05/19 21:18

题意

给出一些正面朝上的硬币的位置,每次可以将一个或者两个或者三个硬币翻面。最右边一个硬币必须是正面的,最后不能操作的人输。

思路

SG打出表,然后能发现SG(n)是有规律的,当2n的二进制位的1的个数是奇数时SG(n)=2*n,否则是2*n+1。
这个规律的证明网上有很多不再赘述,附上SG打表代码。

代码

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>using namespace std;#define LL unsigned long long#define Lowbit(x) ((x)&(-x))#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1|1#define MP(a, b) make_pair(a, b)const int INF = 0x3f3f3f3f;const int MOD = 998244353;const int maxn = 200000 + 7;const double eps = 1e-8;const double PI = acos(-1.0);typedef pair<int, int> pii;int sg[maxn], vis[maxn];void init(){    sg[0] = 1;    for (int i = 1; i <= 20; i++)    {        memset(vis, 0, sizeof(vis));        vis[0] = 1;        for (int j = 0; j < i; j++)            vis[sg[j]] = 1;        for (int j = 0; j < i; j++)            for (int k = 0; k < j; k++)                vis[sg[j]^sg[k]] = 1;        int j = 0;        while (vis[j]) j++;        sg[i] = j;    }    for (int i = 0; i <= 20; i++)        printf("%d %d\n", i, sg[i]);}int main(){    //freopen("H:\\in.txt","r",stdin);    //freopen("H:\\out.txt","w",stdout);    //init();    int n, x;    while (scanf("%d", &n) != EOF)    {        int ans = 0;        set<int> st;        for (int i = 1; i <= n; i++)        {            scanf("%d", &x);            st.insert(x);        }        for (set<int>::iterator it = st.begin(); it != st.end(); it++)        {            x = *it;            x <<= 1;            int cnt = 0;            while (x)            {                cnt += x & 1;                x >>= 1;            }            if (cnt & 1) ans ^= 2 * (*it);            else ans ^= 2 * (*it) + 1;        }        if (!ans) puts("Yes");        else puts("No");    }    return 0;}
0 0