1. 程式人生 > >BZOJ2844-albus就是要第一個出場

BZOJ2844-albus就是要第一個出場

博主連結

題目連結

在這裡插入圖片描述

題意:

給出A陣列,共有N個數,你可以選其中一些出來XOR(至少一個數).
所以可能的XOR結果值排序後去重,問你排在第k個的結果值是多少.

題解:

線性基有個性質:線性基內任意集合異或結果唯一,而所有數異或0還是本身
所以每個數字出現的個數就等於(1*異或值為0的集合個數) = 2^(n-cnt)

所以問題就轉化為求線性基有效位cnt,和q在所有異或值中第幾大

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int
maxn=1e5+7; const int mod=1e9+7; struct Linear_Basis{ ll b[63],nb[63],tot; //b為線性基 nb用來求第K小異或值 tot為nb元素個數 bool flag=false; void Init(){ //初始化 tot=0; flag=false; memset(b,0,sizeof(b)); memset(nb,0,sizeof(nb)); } void Ins(ll x){ //插入 for(int i=62;i>=
0;i--){ if(x&(1ll<<i)){ if(!b[i]){ b[i]=x; return; } x^=b[i]; } } flag=true; return; } bool Fin(ll x){ //驗證存在性 if(x==0&&b[0])return 1; for
(int i=62;i>=1;i--){ int j=i-1; if(x&(1<<j)){ x^=b[j]; if(!x)return 1; } } return 0; } ll Max(ll x){ //求最大值 ll res=x; for(int i=62;i>=0;i--){ res=max(res,res^b[i]); } return res; } ll Min(ll x){ //求最小值 ll res=x; for(int i=0;i<=62;i++){ if(b[i])res^=b[i]; } return res; } ll Rebuild(){ //第K大 for(int i=62;i>=0;i--){ if(b[i]==0)continue; for(int j=i-1;j>=0;j--){ if(b[j]==0)continue; if(b[i]&(1ll<<j))b[i]^=b[j]; } } for(int i=0;i<=62;i++){ if(b[i])nb[tot++]=b[i]; } } ll Kth_Max(ll k){ if(flag)k--; //有一個數沒有存進線性基就k-- ll res=0; if(k==0)return 0; if(k>=(1ll<<tot))return -1; for(int i=62;i>=0;i--){ if(k&(1ll<<i))res^=nb[i]; } return res; } }LB; void Merge(Linear_Basis &a,Linear_Basis &b){//a和b都變成a+b for(int i=62;i>=1;i--){ if(b.b[i]==0)continue; a.Ins(b.b[i]); } b=a; } int id[65],cnt=0; int main(){ int n,a,q; scanf("%d",&n); LB.Init(); for(int i=0;i<n;i++){ scanf("%d",&a); LB.Ins(a); } scanf("%d",&q); ll ans=0; for(int i=0;i<=30;i++)if(LB.b[i])id[cnt++]=i; //記錄線性基中有效位= for(int i=cnt-1;i>=1;i--){ if(!(q>>id[i]&1))continue; ans+=1<<(i-1); //計算比q小的數 計算q為第幾大的線性基 } ans%=10086; for(int i=1;i<=n-cnt;i++){ ans=ans*2%10086; } printf("%d\n",(ans+1)%10086); return 0; }