标签:博弈论
2 2 1 1 3 1 2 3
2 2
题解及代码:
这道题目是和博弈论挂钩的高斯消元。本题涉及的博弈是nim博弈,结论是:当先手处于奇异局势时(几堆石子数相互异或为0),其必败。
那么我们就可以把题目转化成求n堆石子中的k堆石子数异或为0的情况数。使用x1---xn表示最终第i堆石子到底取不取(1取,0不取),将每堆石子数画成2进制的形式,列成31个方程来求自由变元数,最后由于自由变元能取1、0两种状态,所以,最终答案是2^k。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int a[33][110];
int equ,var;
int Gauss()
{
    int k,col,max_r;
    for(k=0,col=0; k<equ&&col<var; k++,col++)
    {
        if(a[k][col]==0)
        {
           max_r=k;
           for(int i=k+1; i<equ; i++)
           if(a[i][col]>a[max_r][col])
           {
               max_r=i;break;
           }
           if(max_r!=k)
           for(int i=0; i<=var; i++)
           {
               swap(a[max_r][i],a[k][i]);
           }
        }
        if(a[k][col]==0)
        {
            k--;
            continue;
        }
        for(int i=k+1; i<equ; i++)
        {
            if(a[i][col])
            for(int j=col; j<=var; j++)
            {
                a[i][j]=a[i][j]^a[k][j];
            }
        }
    }
    return k;
}
int main()
{
    equ=31;
    int cas,n,X,mod=1000007;
    scanf("%d",&cas);
    while(cas--)
    {
        memset(a,0,sizeof(a));
        scanf("%d",&n);
        var=n;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&X);
            int t=0;
            while(X)
            {
                a[t++][i]=X&1;
                X>>=1;
            }
        }
        int k=Gauss(),ans=1;
        k=n-k;
        for(int i=0;i<k;i++)
        {
            ans=(ans*2)%mod;
        }
        printf("%d\n",ans);
    }
    return 0;
}
标签:博弈论
原文地址:http://blog.csdn.net/knight_kaka/article/details/39029913