码迷,mamicode.com
首页 > 其他好文 > 详细

ACM学习历程—HDU 3915 Game(Nim博弈 && xor高斯消元)

时间:2015-11-16 22:25:49      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3915

题目大意是给了n个堆,然后去掉一些堆,使得先手变成必败局势。

首先这是个Nim博弈,必败局势是所有xor和为0.

那么自然变成了n个数里面取出一些数,使得xor和为0,求取法数。

首先由xor高斯消元得到一组向量基,但是这些向量基是无法表示0的。

所以要表示0,必须有若干0来表示,所以n-row就是消元结束后0的个数,那么2^(n-row)就是能组成0的种数。

n==row特判一下。

代码:

技术分享
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long

using namespace std;

const int maxN = 105;
const int MOD = 1000007;
int n, s[maxN];

void input()
{
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
        scanf("%d", &s[i]);
}

//xor高斯消元求线性基
//时间复杂度O(30n)
int xorGauss(int n)
{
    int row = 0;
    for (int i = 30; i >= 0; i--)
    {
        int j;
        for (j = row; j < n; j++)
            if(s[j]&(1<<i))
                break;
        if (j != n)
        {
            swap(s[row], s[j]);
            for (j = 0; j < n; j++)
            {
                if(j == row) continue;
                if(s[j]&(1<<i))
                    s[j] ^= s[row];
            }
            row++;
        }
    }
    return row;
}

void work()
{
    int row, ans, k;
    row = xorGauss(n);
    ans = n-row;
    if (ans != -1)
    {
        k = 1;
        while (ans)
        {
            k <<= 1;
            k %= MOD;
            ans--;
        }
        ans = k;
    }
    else
        ans = -1;
    printf("%d\n", ans);
}

int main()
{
    //freopen("test.in", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int times = 0; times < T; ++times)
    {
        input();
        work();
    }
    return 0;
}
View Code

 

ACM学习历程—HDU 3915 Game(Nim博弈 && xor高斯消元)

标签:

原文地址:http://www.cnblogs.com/andyqsmart/p/4970095.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!