[BZOJ2844]线性基+xor本质不同第K大
https://blog.csdn.net/qq_39759315/article/details/88789872?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4
https://blog.csdn.net/qq_39759315/article/details/88553043?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-6&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-6
input
4
1
2
12
13
13
output
11
拿这个样例来说,构成的线性基为(1,2,12)。13并没有进入其中,因为它与里面的数字xor出来后得到0了。
当我们希望13排第几大的时候,我们要知道它是与哪些数字xor后得到0的。明显知道它是与12,1这两个数字xor变成0的。于是13在所有xor出来的数字中排第5大,这些值是各不相同的
这个与我们上次做的hdu那个求第K大的xor结果,是逆运算。
对于1,2,12三个数字
12 2 1
第1小 0 0 1
第2小 0 1 0
第3小 0 1 1
第4小 1 0 0
第5小 1 0 1
第6小 1 1 0
然后由于线性基只有3个元素,输入的数列中有4个。所以对于没加进去的13这样的元素
如果我们将其加入到选出来的某个子集中,它都使算出来的结果等于另子集中的另一个元素
也就是说所有算出来的结果,都将出现2次。
于是5*2+1=11
还有个空集哟
对于样例
2
1
12
12
输出结果为3.
对于1,12三个数字
12 1
第1小 0 1
第2小 1 0
第3小 1 1
对于询问的12,它是与12进行xor后的。于是排名第2小,加上0,就是第3小了。
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAXN=31; const int mod=10086; ll n,q,ans,cnt,now,a[50]; void insert(ll v){ for(int i=MAXN;i>=0;--i) if((v>>i)&1){ if(a[i]) v^=a[i]; else{ for(int j=i-1;j>=0;--j) if((v>>j)&1) v^=a[j]; for(int j=i+1;j<=MAXN;++j) if((a[j]>>i)&1) a[j]^=v; a[i]=v; break; } } } int main(){ scanf("%lld",&n);ll x; for(int i=1;i<=n;++i){ scanf("%lld",&x);insert(x); } for(int i=0;i<=MAXN;++i) if(a[i]) cnt++; scanf("%lld",&q);ll tmp=cnt; for(int i=MAXN;i>=0;--i) { if(a[i]) { if((q>>i)&1) { ans+=pow(2,tmp-1); } tmp--; } } for(int i=1;i<=n-cnt;++i) ans=ans*2%mod; printf("%lld\n",(ans+1)%mod); return 0; }