[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;
}

 

posted @ 2020-04-24 22:23  我微笑不代表我快乐  阅读(259)  评论(0编辑  收藏  举报