HDU 3915 Game NIM博弈 XOR高斯消元

题目链接:见这里
题意:有n堆石子,每个人只能从某一堆至少拿走一个,不能拿者败。问事先拿走某些堆的石子,使得先手必败。
解法:简单的高斯消元的应用,要求的就是给定n个数中选k个数异或为0的方法数。将n个数用二进制写成n列,之后就很明显了,未知数x1–xn非1即0,表示第i个数取不取。
用高斯消元计算出有多少不确定的变元,这些变元要么是1,要么是0,所以答案即为2的变元数次方。

//HDU 3951

#include <bits/stdc++.h>
using namespace std;
int A[105][105];
int xor_guass(int m, int n) //A是异或方程组系数矩阵 返回秩
{
    int i = 0, j = 0, k, r, u;
    while(i < m && j < n){//当前正在处理第i个方程,第j个变量
        r = i;
        for(int k = i; k < m; k++) if(A[k][j]){r = k; break;}
        if(A[r][j]){
             if(r != i) for(k = 0; k <= n; k++) swap(A[r][k], A[i][k]);
             //消元完成之后第i行的第一个非0列是第j列,且第u>i行的第j列全是0
            for(u = i + 1; u < m; u++) if(A[u][j])
                for(k = i; k <= n; k++) A[u][k] ^= A[i][k];
            i++;
        }
        j++;
    }
    return i;
}
int main()
{
    int T, n, ks = 0; scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        int maxp = 0;
        memset(A, 0, sizeof(A));
        for(int i = 0; i < n; i++){
            int x;
            scanf("%d", &x);
            int cnt = 0;
            while(x != 0){
                A[cnt++][i] = x&1;
                x >>= 1;
            }
            maxp = max(maxp, cnt);
        }
        for(int i = 0; i < maxp; i++) A[i][n] = 0;
        int cc = xor_guass(maxp, n);
        int ans = 1;
        for(int i = 0; i < n - cc; i++) ans = ans * 2 % 1000007;
        printf("%d\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值