ZOJ_3964 Yet Another Game of Stones(博弈论)

Yet Another Game of Stones

Time Limit: 1000 ms
Memory Limit: 65536 KB
Problem Description

Alice and Bob are playing yet another game of stones. The rules of this game are as follow:

  • The game starts with n piles of stones indexed from 1 to n. The i-th pile contains ai stones and a special constraint indicated as bi.
  • The players make their moves alternatively. The allowable moves for the two players are different.
  • An allowable move of Bob is considered as removal of some positive number of stones from a pile.
  • An allowable move of Alice is also considered as removal of some positive number of stones from a pile, but is limited by the constraint bi of that pile.
  • If bi = 0, there are no constraints.
  • If bi = 1, Alice can only remove some odd number of stones from that pile.
  • If bi = 2, Alice can only remove some even number of stones from that pile.
    Please note that there are no constraints on Bob.
  • The player who is unable to make an allowable move loses.

Alice is always the first to make a move. Do you know who will win the game if they both play optimally?

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains an integer n ( 1 ≤ n ≤ 1 0 5 1 ≤ n ≤ 10^5 1n105), indicating the number of piles.

The second line contains n integers a 1 a_1 a1, a 2 a_2 a2, …, a n a_n an ( 1 ≤ a i ≤ 109 1 ≤ a_i ≤ 109 1ai109), indicating the number of stones in each pile.

The third line of each test case contains n integers b 1 b_1 b1, b 2 b_2 b2, …, b n b_n bn ( 0 ≤ b i ≤ 2 0 ≤ b_i ≤ 2 0bi2), indicating the special constraint of each pile.

It is guaranteed that the sum of n over all test cases does not exceed 106.

We kindly remind you that this problem contains large I/O file, so it’s recommended to use a faster I/O method. For example, you can use scanf/printf instead of cin/cout in C++.

Output

For each test case, output “Alice” (without the quotes) if Alice will win the game. Otherwise, output “Bob” (without the quotes).

Sample Input

3
2
4 1
1 0
1
3
2
1
1
2

Sample Output

Alice
Bob
Bob

题意

A和B在进行取石子游戏,每次可以从一堆中去任意正整数数量的式子,对A的操作有限制。每堆石子有两个值 a i , b i a_i,b_i ai,bi a i a_i ai代表石子数量, b i b_i bi代表对A的限制。 b i = = 0 b_i==0 bi==0无限制; b i = = 1 b_i==1 bi==1,A只能从此堆中取奇数个; b i = = 2 b_i==2 bi==2,A只能从此堆中取偶数个。无法操作的人输,A先手,谁必胜。

题解:

首先只考虑 b i = = 0 b_i==0 bi==0的那部分石子,求出其异或和 s i g sig sig。考虑 b i ! = 0 b_i!=0 bi!=0,第 i i i组, a i a_i ai b i b_i bi的奇偶性不同,显然A是没办法一次把这堆取完的,则此时无论B面对的 s i g sig sig是必胜态还是必败态,都选择是否操作A无法取完的那堆保证B必胜。如果有多堆 b i ! = 0 bi!=0 bi!=0,且他们奇偶性相同,B可以操作某堆,使形成上一条的局面。注意初始 a i = = 1 ∧ b i = = 1 a_i == 1 \land b_i == 1 ai==1bi==1时,A可以任取,所以将其作为 b i = = 0 b_i==0 bi==0来考虑。

结合上面考虑A必胜的情况。

  • 不存在 b i ! = 0 b_i!=0 bi!=0的组,显然 s i g ! = 0 sig!=0 sig!=0,A必胜;
  • 只存在一组 b i ! = 0 b_i!=0 bi!=0,且那组 b i b_i bi a i a_i ai奇偶性相同, s i g = = 0 sig==0 sig==0,则A可以取完那组,B面临 s i g = = 0 sig==0 sig==0,A必胜
  • 只存在一组 b i = = 1 b_i==1 bi==1,且 a i a_i ai为偶数,则a可以直接将其取剩下一个, b i = 1 , a i ′ = 1 b_i=1,a_i'=1 bi=1,ai=1,B先手,若 s i g = 1 sig=1 sig=1,A必胜。
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-7
 
using namespace std;
typedef long long LL;   
typedef pair<LL, int> P;
const int maxn = 100010;
const int mod = 998244353;
int a[maxn], b[maxn];

int main()
{
    int t, n, i, j, k, sig, n1, n2, n3;
    scanf("%d", &t);
    while(t--)
    {
        n1 = n2 = n3 = sig = 0;
        scanf("%d", &n);
        for(i=0;i<n;i++)
            scanf("%d", &a[i]);
        for(i=0;i<n;i++)
            scanf("%d", &b[i]);
        for(i=0;i<n;i++){
            if(b[i] == 0)sig ^= a[i];
            else if(b[i] == 1 && a[i] == 1)sig ^= 1;
            else if(a[i]%2 == b[i]%2)n1++;
            else {
                n2++;
                if(b[i] == 1)n3++;
            }
        }
        if(n1 == 0 && n2 == 0 && sig)
            printf("Alice\n");
        else if(n1 == 1 && n2 == 0 && sig == 0)
            printf("Alice\n");
        else if(n2 == 1 && n1 == 0 && n3 == 1 && sig == 1)
            printf("Alice\n");
        else printf("Bob\n");
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值