题意:给你一个数列A。将所有可能异或出的值从小到大排列。问x是第几个。ai<=1e9,n<=100000.
标程:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 typedef long long ll; 6 const int mod=10086; 7 int cnt[32],n,x,tot,s[32],ans; 8 void ins(int x) 9 { 10 for (int i=31;i>=0;i--) 11 if ((x>>i)&1) 12 if (!cnt[i]) {cnt[i]=x;break;} 13 else x^=cnt[i]; 14 } 15 int ksm(int x,int y) 16 { 17 int res=1; 18 while (y) {if (y&1) res=(ll)res*x%mod; x=(ll)x*x%mod; y>>=1;} 19 return res; 20 } 21 int main() 22 { 23 scanf("%d",&n); 24 for (int i=1;i<=n;i++) scanf("%d",&x),ins(x); 25 for (int i=0;i<=31;i++) 26 if (cnt[i]) tot++,s[i]=tot; 27 int d=ksm(2,n-tot); 28 scanf("%d",&x); 29 for (int i=31;i>=0;i--) 30 if (((x>>i)&1)&&s[i]) ans=((ll)ans+(1<<s[i]-1))%mod; 31 ans=(ll)ans*d%mod; 32 printf("%d\n",(ans+1)%mod); 33 return 0; 34 }
题解:线性基
用映射可证每一个可能被异或出的值出现2^(n-线性基元素个数),最后乘一下即可。
在线性基中进行消元,那么每一位的1只有可能在线性基的一个位置上。异或出一个数相当于在位置上增加1。
询问的x若能用s1^s2^s3^...^sk表示,那么可以用:不取最高位,其他任取;取最高位,第二位不取,其他任取;取最高位第二位,不取第三位,其他任取,……这样统计出能够异或出的互不相同的<x的值有多少个。也就是对于该位在x中是1且存在的每一个线性基统计。