就是要第一个出场的albus 【BZOJ】 线性基
就是我代码里读入之后的那一部分。
1.(一下a[]为原数组 a'[]为线性基)
线性基 中的a'[i]其实 是 原来的a[]中的某个子集(2^n个子集中的某个) 异或出来的 可能会有其他的子集与它异或和相同,a'[i]代表了 这个集合。
线性基的大小是log的,因为 a[]中异或和等于a'[i]的集合可能有好多 而线性基则 通过异或消掉了这些 重复的。
2.
假设a[]大小为n 线性基大小为k,则a[]和a'[] 都有且仅有2^k种 异或和不同 的子集【清楚线性基定义的话 这是显然的】
然而由于本题 要保留重复的, 那么另一个性质就是 a'[]可异或出的2^k种异或和 在a[]可异或出的2^n个有重复的值中 每个不同的值都有2^(n-k)个。
所以最后ans要*2^(n-k)
1 #include <bits/stdc++.h> 2 #define mo 10086 3 using namespace std; 4 int b[50],a[100005],n,m,k,t,x,y,z,p,q,ans; 5 int main(){ 6 scanf("%d",&n); 7 for (int i=1;i<=n;++i) scanf("%d",&a[i]); 8 scanf("%d",&m); k=0; 9 for (int i=1<<29;i;i>>=1){ 10 for (int j=k+1;j<=n;++j) 11 if (a[j]&i){ 12 swap(a[j],a[++k]); b[k]=i; 13 for (int o=1;o<=n;++o) 14 if (o!=k&&a[o]&i) a[o]^=a[k]; 15 break; 16 } 17 } 18 for (int i=1;i<=k;++i) 19 if ((x^a[i])<=m){ 20 x^=a[i]; 21 (ans+=(1<<k-i)%mo)%=mo; 22 } 23 for (int i=k+1;i<=n;++i) (ans<<=1)%=mo; 24 ++ans%=mo; printf("%d",ans); 25 return 0; 26 }
转载请标明出处 http://www.cnblogs.com/cyz666/