G. (Zero XOR Subset)-less(线性基)

题目链接:http://codeforces.com/contest/1101/problem/G

题目大意:给你n个数,然后让你把这n个数分成尽可能多的集合,要求,每个集合的值看做这个集合所有元素的异或值,并且任意个集合对应的值,再进行异或也不能为0,然后如果不存在合理的分法的时候,输出-1。否则,输出能分出的最大的集合个数。

具体思路:求出这n个数的线性基就完事了,对于-1的情况,就是这n个值得异或值是0,这个时候无论你怎么分都是不管用的,其他情况直接输出线性基就可以了。

线性基的定义: 对于n个数,a1,a2,a3,a4.线性基b1,b2......,线性基满足的情况是这n个数,其中的任意个数的异或值都能用数组b中的某几个数求出来。

具体方法:一个数一个数的来,对于当前的数的首位(二进制),当前i位是1的时候,如果这一位没有被记录过,就让b[i]=a[i].否则,让a[i]^=b[i],继续往下走就可以了。

那么这个题为什么求线性基就可以了呢?我们可以通过求线性基的过程发现线性基的一个性质,线性基中的任意几个数都不可能异或是0,这个性质我们可以通过反证法来进行,如果异或是0的话,那就说明这个这几个数中,存在可以互相表达的情况,这就有违求线性基的过程了。

 AC代码:

#include
using namespace std;
# define ll long long
const int maxn = 2e5+100;
int a[maxn],p[100];
void cal(int n)
{
    for(int i=1; i<=n; i++)
    {
        if(a[i]==0)continue;
        for(int j=63; j>=0; j--)
        {
            if((a[i]&(1<=0;i--){
        if(p[i])num++;
        }
        printf("%d\n",num);
    }
    return 0;
}

 

你可能感兴趣的:(线性基)