bzoj2844albus就是要第一个出场解题报告
题意
给出n个数,在这n个数中选任意多的数进行异或,共产生了2n个含重复数字的数,现给出一个数q,问若将q插入这2n个数中,q是第几小的
算法分析
先对着n个数进行高斯消元,得到m个非零数和n-m个0,那m个非零的值就可组成2n种数,每个重复2n-m次。只要按位统计q在其中排在第几位就可以了。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
const int nn=100005;
const int MOD=10086;
int s[nn];
bool f[50];
int n,m,q;
inline int gauss(int n){
int j(0), k;
for (int i=30;i>=0;--i)
{
for (k = j;k < n;++k){
if ((s[k] >> i) & 1){
break;
}
}
if (n == k) continue;
int t;
t = s[j]; s[j] = s[k]; s[k] = t;
for (int k=0;k<n;++k)
if (k != j && ((s[k] >> i) & 1)) s[k] ^= s[j];
++j;
}
return j;
}
int main(){
freopen("bzoj2844.in", "r", stdin);
freopen("bzoj2844.out", "w", stdout);
scanf("%d", &n);
for (int i=0;i<n;++i) scanf("%d", &s[i]);
memset(f, false, sizeof(f));
q=gauss(n);
long long p=0;
scanf("%d", &m);
int now=0;
for (int i=0;i<q;++i)
{
long long st = 1 << (q - i - 1);
if ((now ^ s[i]) <= m){
p += st;
now ^= s[i];
if (now == m) break;
}
}
long long c=1;
for (int i=0;i<(n-q);++i) c = (c << 1) %MOD;
p = (p * c + 1) % MOD;
printf("%lld\n", p);
fclose(stdin);
fclose(stdout);
return 0;
}