題意:
給你n個數,要你從中取出若干個進行異或運算,求最後所有可以得到的異或結果中的
第k小的異或值。n<=10^18
這個題是用來研究xor性質的一道好題。
首先我們可以暴力地找出些規律,我們發現不管拿出多少個數,他們能xor到的數,出現的次數都是一樣的,並且都是2的倍數。事實上,我們不論用原數ai還是ai xor aj得到的數,去xor起來得到的數都是這些。
這樣我們可以想方設法地化簡我們用到的基數,也就是找到一組基數使得它們能夠xor出所有原數能xor出的數,並且要盡量簡單。我們可以模仿高斯消元的過程,就是把每個數當成一行二進位制數去消元,然後保留乙個類似上三角的東西,從高位向低位每一行保留連續的幾個1,這些1行與行之間是不重複的,但每一行之中還會有額外的一些1,這些1是可重複的,就造成了一些數是xor不出來的。
假設我們選出了m行,也就是m個基數,那麼我們可以xor出2m個數,如果總共給你了n個數,那麼就有n-m個數是可以被那些基數完全替代的,這些行在高斯消元的過程中就是自由變數。這些行的值為0,也就是它去xor任意乙個數,原數都不會改變,這樣就產生了2n-m個重複的數,這樣便驗證了我們一開始的結論。
其實這組基數還有乙個很好的性質,就是xor出的第k大(去重)的數,恰好是k二進位制分解後對應位上的基數xor起來的到的數。因為從上到下每個基數代表了從高到低的一些二進位制位,那麼我們就相當於用這些連續的二進位制位去組合形成所有的數。
那對於這個題來說,我們要求第k大的數,我們把m行基數求出來了以後,選出k的各個二進位制位對應的基數,xor起來就是答案。
注意long long,注意0的情況。
**其中gauss部分,可以作為解模2的方程組的優化。
#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
unsigned __int64 a[123450];
unsigned __int64 bit[66];
int n;
void debug()
while(t--)
{int i;
cin>>n;
int nofree;
for(i=0; i>q;
printf("case #%d:\n",cas++);
while(q--)
{unsigned __int64 k;
scanf("%i64u",&k);
if(nofree=((unsigned __int64)1<
線性基 HDU3949 XOR 題解
給出 n n 個數,求選出的非空集合中異或和第 k role presentation k k小的異或和 異或和相同算一次 沒有 k k 個輸出 1 role presentation 1 1。如果構造線性基時將矩陣消成對角矩陣,得到的線性基就有乙個很棒的性質 最高位為 i i 的數至多只有乙個,且...
HDU 3949 XOR(線性基板子)
題目大意 給定n nn個數以及q個詢問,每個詢問要求輸出這n nn個數的所有非空子集的異或值中第k kk小的值,若不存在該值輸出 1。思路 裸的線性基,順便放個板子。維護線性基時一定要從低位往高位維護。ac include include include include include includ...
HDU 3949 XOR 線性基 高斯消元
hdu 3949 xor hdu3949xor 搞死消元找到一組線性無關組 消出對角矩陣後 對於k二進位制拆分 對於每列只有有乙個1的,顯然可以用k的二進位制數直接異或得到第k大 對於一列由多個1的,由於二進位制性質,由於2的冪 1次方比2的 1到冪 的和要大,所以不影響大小 include inc...