BZOJ2844 albus就是要第一个出场

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2844

 

这题貌似HDU上有一道差不多的题,不过我没做过,也就没管了。

首先讲一个线性基的东西,大概就是这样:

 

然后就是一个什么性质:S异或起来会出现重复,但是重复了多少次呢?

若我构造一个大小为k的线性基,那么重复了2^(n-k)次。

然后构造出需要的数,就每次找到能消去位数的地方消去就好。

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

using namespace std;

const int maxn=100010;
const int mod=10086;

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

int n,m,k;
int a[maxn],b[maxn];

void gauss(){
    k=n;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++)
            if(a[j]>a[i]) swap(a[i],a[j]);
        if(!a[i]){k=i-1;break;}
        for(int j=30;j>=0;j--)
            if((a[i]>>j)&1){
                b[i]=j;
                for(int x=1;x<=n;x++)
                    if(x!=i && (a[x]>>j)&1)
                        a[x]^=a[i];
                break;
            }
    }
}   

inline int power(int x,int y){
    int t=1;
    for(;y;y>>=1,x=x*x%mod)
     if(y&1) t=t*x%mod;
    return t;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("2844.in","r",stdin);
    freopen("2844.out","w",stdout);
#endif
    n=in();
    for(int i=1;i<=n;i++) a[i]=in();
    m=in();
    gauss();
    int ans=1;
    for(int i=1;i<=k;i++)
        if((m>>b[i])&1){
            m^=a[i];
            ans=(ans+power(2,n-i))%mod;
        }
    printf("%d",ans);    
    return 0;
}
View Code

 

posted @ 2016-03-01 15:13  诚叙  阅读(517)  评论(0编辑  收藏  举报