HDU 3949 XOR ——线形基 高斯消元

【题目分析】

    异或空间的K小值。

    高斯消元和动态维护线形基两种方法都试了试。

    动态维护更好些,也更快(QAQ,我要高斯消元有何用)

    高斯消元可以用来开拓视野。

    注意0和-1的情况

【代码】

高斯消元

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 10005
#define ll long long
#define F(i,j,k) for (ll i=j;i<=k;++i)
#define D(i,j,k) for (ll i=j;i>=k;--i)

void Finout()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    #endif
}

inline ll read()
{
    ll x=0;char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}

int T,n,m,tot,zero;
ll bin[65],a[maxn];

void gauss()
{
	tot=zero=0;
	for (ll i=bin[60];i;i>>=1)
	{
		int j=tot+1;
		while (!(i&a[j])&&j<=n) j++;
		if (j==n+1) continue;
		tot++;
		swap(a[tot],a[j]);
		F(k,1,n)
			if (k!=tot&&(a[k]&i))
				a[k]^=a[tot];
	}
	if (tot!=n) zero=1;
}

ll query(ll x)
{
	ll sum=0; x-=zero;
	if (!x) return 0;
	if (x>=bin[tot]) return -1;
	F(i,1,tot) if (x&bin[tot-i]) sum^=a[i];
	return sum;
}

int main()
{
	Finout();
	bin[0]=1;F(i,1,60) bin[i]=bin[i-1]<<1;
	T=read();
	F(z,1,T)
	{
		memset(a,0,sizeof a);
		printf("Case #%d:\n",z);
		n=read(); F(i,1,n) a[i]=read();
		gauss();
		m=read();
		while (m--)
		{
			int x=read();
			printf("%lld\n",query(x));
		}
	}
}

动态维护线形基

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define ll long long
#define F(i,j,k) for (ll i=j;i<=k;++i)
#define D(i,j,k) for (ll i=j;i>=k;--i)

void Finout()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    #endif
}

ll Getll()
{
    ll x=0; char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); }
    return x;
}

ll T,Q,n,x,tab,kas=0;;
ll a[10001],lb[70],rk;

bool cmp(ll x,ll y)
{return x>y;}
bool cmp2(ll x,ll y)
{return x<y;}

int main()
{
    scanf("%lld",&T);
    while (T--)
    {
        printf("Case #%lld:\n",++kas);
        tab=1;
        ll flag=0,cnt=0;
        memset(lb,0,sizeof lb); 
        scanf("%lld",&n);
        F(i,1,n) scanf("%lld",&a[i]);
        F(i,1,n)
        {
            D(j,63,0)
            if ((a[i]>>j)&1){
                if (lb[j]) a[i]^=lb[j];
                else
                {
                    cnt++;
                    lb[j]=a[i];
                    F(k,0,62)
                        F(r,k+1,63)
                            if ((lb[r]>>k)&1)
                                lb[r]^=lb[k];
                    break;
                }
            }
            if (!a[i]) flag=1;
        }
        cnt=0;
        for (int i=0;i<=63;++i)
        {
            if (lb[i]) lb[cnt++]=lb[i];
        }
        scanf("%lld",&Q);
        F(i,1,Q)
        {
            scanf("%lld",&rk); rk-=flag; ll sum=0;
            if (rk>>cnt) printf("-1\n");
            else
            {
                F(j,0,cnt-1) if ((rk>>j)&1) sum^=lb[j];
                printf("%lld\n",sum);
            }
        }
    }
}

  

posted @ 2017-01-23 19:15  SfailSth  阅读(115)  评论(0编辑  收藏  举报