for(int i =0; i <=30;++i)if(~A.g[i])for(int j = i -1; j >=0;--j)if((~A.g[j])&&(1<< j & A.g[i]))
A.g[i]^= A.g[j];
相当于线性基中的元素与其它元素异或,得到的仍满足线性基的性质。
此时线性基中任一元素都要满足:最高位的 1 在线性基中只出现一次。
因此构成 Q 的唯一方案为:Q 的所有为 1 的位在线性基中对应且存在的元素的异或和。
考虑小于 Q 的子集至少都要不选取这些元素中的其中一些,我们枚举这些元素中不选取的位数最高的元素(假设为从低到高为第 i 个存在的元素),那么位数更低的元素显然可以随便选,对 cnt 的贡献为 2i。
时间复杂度 O(30n)。
Code
转化后显然对最高位的 1 不影响,实现时可以不写转化的部分。
#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cctype>#include<cstdio>constint Ss =1<<20;char frd[Ss],*ihead = frd + Ss;constchar*itail = ihead;inlinecharnxtChar(){if(ihead == itail)fread(frd,1, Ss,stdin), ihead = frd;return*ihead++;}template<classT>inlinevoidread(T &res){char ch;while(ch =nxtChar(),!isdigit(ch));
res = ch ^48;while(ch =nxtChar(),isdigit(ch))
res = res *10+ ch -48;}typedeflonglong ll;constint mod =10086;constint N =1e5+5;int n, m, ans, top;int stk[35];struct Basis
{int g[35];inlinevoidClear(){for(int i =30; i >=0;--i)
g[i]=-1;}inlinevoidInsert(int x){for(int i =30; i >=0;--i)if(1<< i & x){if(g[i]==-1)return(void)(g[i]= x);
x ^= g[i];}}}A;inlineintksm(int x,int k){int res =1;while(k){if(k &1) res =1ll* res * x % mod;
x =1ll* x * x % mod; k >>=1;}return res;}intmain(){
A.Clear();read(n);for(int i =1, x; i <= n;++i)read(x), A.Insert(x);int Q;read(Q);for(int i =0; i <=30;++i)if(~A.g[i]) stk[top++]= i;for(int i = top -1; i >=0;--i)if(Q >> stk[i]&1) ans +=1<< i;printf("%d\n",(1ll* ans *ksm(2, n - top)+1)% mod);}