nim游戏

nim游戏的规则:有两个人和 n n n堆石子,第 i i i堆石子有 a i a_i ai个,每人每次可以从任意一堆石子中取出任意多个石子。可以整堆取完,但不能不取。最后没有石子可取的人就输了。两人都用最优策略,请问是否有先手必胜的策略。

先给出结论。如果 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n ≠ 0 a_1\oplus a_2\oplus \dots \oplus a_n\neq 0 a1a2an=0,则有先手必胜策略,否则没有。

为什么呢?对于 > 0 >0 >0的情况,我们设 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n = k a_1\oplus a_2\oplus \dots \oplus a_n=k a1a2an=k,则因为 k k k二进制中的最高位是从 a a a值中来的,所以必定有一个 i i i,若 k k k二进制的最高位是第 t t t位,则 a i a_i ai二进制中的第 t t t位为 1 1 1

我们取若干个第 i i i堆石子,使的数量变为 a i ⊕ k a_i\oplus k aik(这里可以保证 a i ⊕ k < a i a_i\oplus kaik<ai,因为 k k k的最高位被消去),那么 a 1 ⊕ a 2 ⊕ … ( a i ⊕ k ) ⊕ ⋯ ⊕ a n = a 1 ⊕ a 2 ⊕ … a i ⊕ ⋯ ⊕ a n ⊕ k = 0 a_1\oplus a_2\oplus \dots (a_i\oplus k)\oplus \dots \oplus a_n=a_1\oplus a_2\oplus \dots a_i \oplus \dots \oplus a_n \oplus k=0 a1a2(aik)an=a1a2aiank=0

作为先手,我们只需要使得各堆石子的数量的异或和为 0 0 0。因为不能不拿,所以后手必然会使得各堆石子的异或和不为 0 0 0。我们只要在每次操作中使异或和为 0 0 0,因为石子只会越来越少,所以最后使各堆石子数量变为 0 0 0的只能是先手。

如果 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n = 0 a_1\oplus a_2\oplus \dots \oplus a_n= 0 a1a2an=0,先手不管怎么取,都会使各堆石子的异或和不为 0 0 0,只要后手每次操作都是各堆石子的异或和为 0 0 0,那后手就是最后的赢家。

结论:如果 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n ≠ 0 a_1\oplus a_2\oplus \dots \oplus a_n\neq 0 a1a2an=0,则有先手必胜策略,否则没有。

例题

P2197 nim游戏

同上文

code

#include
using namespace std;
int t,n,ans,a[10005];
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        ans=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            ans^=a[i];
        }
        if(ans) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

你可能感兴趣的:(有趣博弈论,c++)