标签:博弈论
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