您的位置:首页 > 其它

BZOJ 2844: albus就是要第一个出场 [高斯消元XOR 线性基]

2017-02-19 11:53 417 查看

2844: albus就是要第一个出场

题意:给定一个n个数的集合S和一个数x,求x在S的$2^n$个子集从小到大的异或和序列中最早出现的位置

一开始看错题了...人家要求的是x第一次出现位置不是第x个是谁

求出线性基后我们知道一共有$2^r$个不同的数,再知道每个数出现了几次就好啦

每个数出现了$2^{n-r}$次....因为有$n-r$个线性相关(高斯消元后全0了)的方程异或不影响....

然后就简单了,从高到低枚举二进制位,异或这一位后小于k就加上

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bitset>
using namespace std;
typedef long long ll;
const int N=1e5+5,INF=1e9,P=10086;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int n,x;
int a
,bin[70];
void ini(){
bin[0]=1;for(int i=1;i<=30;i++) bin[i]=bin[i-1]<<1;
}
int now;
void Gauss(){
now=1;
for(int i=30;i>=0;i--){
int j=now;
while(j<=n&&!(a[j]&bin[i])) j++;
if(j==n+1) continue;
if(j!=now) swap(a[j],a[now]);
for(int k=1;k<=n;k++)
if(k!=now&&(a[k]&bin[i])) a[k]^=a[now];
now++;
}
now--;
}
int main(){
freopen("in","r",stdin);
ini();
n=read();
for(int i=1;i<=n;i++) a[i]=read();
Gauss();
x=read();
int val=0,sum=0;
for(int i=1;i<=now;i++) if((val^a[i])<=x){
val^=a[i];
sum=(sum+(1<<(now-i))%P)%P;
}
for(int i=1;i<=n-now;i++) sum=(sum<<1)%P;
printf("%d",(sum+1)%P);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: