Codeforces 1384D. GameGame(博弈)

Koa the Koala and her best friend want to play a game.

The game starts with an array 𝑎 of length 𝑛 consisting of non-negative integers. Koa and her best friend move in turns and each have initially a score equal to 0. Koa starts.

Let’s describe a move in the game:

During his move, a player chooses any element of the array and removes it from this array, xor-ing it with the current score of the player.
More formally: if the current score of the player is 𝑥 and the chosen element is 𝑦, his new score will be 𝑥⊕𝑦. Here ⊕ denotes bitwise XOR operation.

Note that after a move element 𝑦 is removed from 𝑎.

The game ends when the array is empty.
At the end of the game the winner is the player with the maximum score. If both players have the same score then it’s a draw.

If both players play optimally find out whether Koa will win, lose or draw the game.

Input
Each test contains multiple test cases. The first line contains 𝑡 (1≤𝑡≤104) — the number of test cases. Description of the test cases follows.

The first line of each test case contains the integer 𝑛 (1≤𝑛≤105) — the length of 𝑎.

The second line of each test case contains 𝑛 integers 𝑎1,𝑎2,…,𝑎𝑛 (0≤𝑎𝑖≤109) — elements of 𝑎.

It is guaranteed that the sum of 𝑛 over all test cases does not exceed 105.

Output
For each test case print:

WIN if Koa will win the game.
LOSE if Koa will lose the game.
DRAW if the game ends in a draw.
Examples
inputCopy
3
3
1 2 2
3
2 2 3
5
0 0 0 2 2
outputCopy
WIN
LOSE
DRAW
inputCopy
4
5
4 1 5 1 3
4
1 0 1 6
1
0
2
5 4
outputCopy
WIN
WIN
DRAW
WIN
Note
In testcase 1 of the first sample we have:

𝑎=[1,2,2]. Here Koa chooses 1, other player has to choose 2, Koa chooses another 2. Score for Koa is 1⊕2=3 and score for other player is 2 so Koa wins.

题意:
n n n个数,每个人选数。
值为所选数的异或值,所得值大的人获胜。求先手必胜与否。

思路:
直观的思路是考虑最高位。
如果最高位的1有偶数个,每个人肯定是取一半,不管。
如果有奇数个,先手必胜。

但是这样会有问题。
假设当前最高位1的个数为 c n t cnt cnt,且 c n t cnt cnt为奇数,则有可能 ( c n t + 1 ) / 2 (cnt+1)/2 (cnt+1)/2为偶数,也就是先手可能选了偶数个,反而不如后手优。所以要特判一下。

如果 c n t = 2 ∗ x + 2 ∗ x + 1 cnt=2*x+2*x+1 cnt=2x+2x+1 ( x ≥ 0 ) (x≥0) x0
( c n t + 1 ) / 2 = 2 ∗ x + 1 (cnt+1)/2=2*x+1 (cnt+1)/2=2x+1一定是奇数,所以先手必胜。

否则就是 c n t = 2 ∗ x + 2 ∗ x − 1 cnt=2*x+2*x-1 cnt=2x+2x1 ( x ≥ 1 ) (x≥1) x1
( c n t + 1 ) / 2 = 2 ∗ x (cnt+1)/2=2*x (cnt+1)/2=2x一定是偶数。
则当n为奇数的时候,当前最高位为0的数有偶数个,先手后手取一半。然后先手只能取一半当前最高为1的数了,所以先手必败。
否则先手必胜。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

typedef long long ll;
const int maxn = 3e5 + 7;
const int INF = 2e9;

int a[maxn];

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        int n;scanf("%d",&n);
        for(int i = 1;i <= n;i++) {
            scanf("%d",&a[i]);
        }
        int flag = 0;
        for(int i = 30;i >= 0;i--) {
            int cnt = 0;
            for(int j = 1;j <= n;j++) {
                if(a[j] & (1 << i)) {
                    cnt++;
                }
            }
            if(cnt % 2 == 1) {
                if(cnt % 4 == 1) {
                    flag = 1;
                } else {
                    if(n % 2 == 1) flag = -1;
                    else flag = 1;
                }
                break;
            }
        }
        if(flag == 1) {
            printf("WIN\n");
        } else if(flag == 0) {
            printf("DRAW\n");
        } else {
            printf("LOSE\n");
        }
    }
    return 0;
}

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

typedef long long ll;
const int maxn = 3e5 + 7;
const int INF = 2e9;

int a[maxn];

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        int n;scanf("%d",&n);
        for(int i = 1;i <= n;i++) {
            scanf("%d",&a[i]);
        }
        int flag = 0;
        for(int i = 30;i >= 0;i--) {
            int cnt = 0;
            for(int j = 1;j <= n;j++) {
                if(a[j] & (1 << i)) {
                    cnt++;
                }
            }
            if(cnt % 2 == 1) {
                if(cnt % 4 == 1) {
                    flag = 1;
                } else {
                    if(n % 2 == 1) flag = -1;
                    else flag = 1;
                }
                break;
            }
        }
        if(flag == 1) {
            printf("WIN\n");
        } else if(flag == 0) {
            printf("DRAW\n");
        } else {
            printf("LOSE\n");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值