【 hdu3949 XOR】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sxy201658506207/article/details/84667672

从n个数中任选m(m>=1)个数异或起来,求所有可能的异或和的第k小值。

用到了0能不能被异或出来的问题。如果线性基的大小和原数组一样,0是不能被异或出来的,否则可以。
在求k小值的时候要注意
 

#include<bits/stdc++.h>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <stdlib.h>
#include <ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 1e6 + 5;
using namespace std;
ll a[10005],m;
ll p[10005];
bool flag;
int cnt=0;
void init()
{
    memset(a,0,sizeof(a));
    memset(p,0,sizeof(p));
    cnt=0;
    flag=false;
}
void build(ll p)
{
    for(int x=62;x>=0;--x)
    {
       if(p&ll(1ll<<x))
        {
            if(a[x]==0)
            {
                a[x]=p;
                break;
            }
            p^=a[x];
        }
    }
    if(p==0) flag=true;
}
void rebuild()
{
    for(int i=62;i>=0;--i)
    {
        if(a[i]==0)continue;//
        for(int j=i-1;j>=0;--j)
        {
            if(a[j]==0)continue;
            if(a[i]&ll(ll(1<<j)))
                a[i]^=a[j];
        }
    }
    for(int i=0;i<=62;++i)
        if(a[i])
        p[cnt++]=a[i];
}
ll query_Kth(ll k)
{
    ll ret=0;
    if(flag) k--; 
    if(k==0) return 0;
    if(k>=ll(1LL<<cnt))return -1;
    for(int i=62;i>=0;--i)
        if(k&ll(1ll<<i))ret^=p[i];
    return ret;
}
int main()
{
    int T,n;
	cin>>T;
	for(int ca=1;ca<=T;ca++)
	{
		init();
		printf("Case #%d:\n",ca);
		cin>>n;
		for(int i=1;i<=n;i++)
		{
		    cin>>m;
		     build(m);
		}
		rebuild();
		int t;
		cin>>t;
		while(t--)
		{
			ll x;
			cin>>x;
            printf("%lld\n",query_Kth(x));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sxy201658506207/article/details/84667672