求集合中選乙個數與當前值進行位運算的max

2022-03-20 04:57:56 字數 1164 閱讀 5903

這是乙個聽來的神仙東西。

先確定一下值域把,大概\(2^\),再大點也可以,但是這裡就只是寫寫,所以無所謂啦。

我們先看看如果暴力求怎麼做,位運算需要給定\(01/10,00,11\)的關係,總共\(8\)種。

如果是暴力的話,我們的方法有兩種,

第一種是比較喜聞樂見的,

我們對於當前數\(x\),暴力計算所有存在的數\(a_i\)中,\(x\oplus a_i\)的最大值,這樣的複雜度是\(o(2^)\)的。

另外一種也是不難考慮到的,

我們對於每個可能出現的數維護乙個當前所有數的最大值。

也就是對於所有值域中的數,維護乙個答案\(ans\)

然後依次插入所有集合中所有的數\(a_i\),每次暴力計算所有的答案的最大值,

也就是\(ans[x]=max\\),這樣子詢問的時候可以\(o(1)\)查詢。

兩種方法一種是插入\(o(1)\)詢問\(o(n)\),另外乙個是插入\(o(n)\),詢問\(o(1)\)

我們把兩種東西結合一下,這樣可以得到乙個\(o(\sqrt n)\)的方法。

大致的方法如下:

我們對於每個數從中間分開,拆成前\(8\)個二進位制位和後\(8\)個二進位制位。

這樣子我們可以預處理乙個陣列\(pre[i][j]\),

表示集合中乙個前\(8\)位是\(i\)的數,後\(8\)位能夠和\(j\)進行位運算的最大值。

這樣子\(i,j\)都是乙個\(8\)位的數,總的空間和上述方法一樣。

因為位運算是可以按位貪心的,所以對於查詢乙個數\(x\)

我們把它拆成\(x=a\times 2^8+b\),

每次先暴力\(for\)所有可能的前\(8\)位,找到與\(a\)能夠構成最大值的那些數,

然後對於找到的所有數的前八位\(p\),直接查\(pre[p][b]\),

因為前八位更大的數一定更大,那麼影響結果的就只剩下後八位了,

把兩個部分拼接起來就好了。

這樣子暴力\(for\)前八位的複雜度是\(o(2^8)\)

查詢後面部分最大值的複雜度是\(o(1)\)

所以這樣子總的複雜度\(o(2^8)\)。

而對於集合中插入乙個數,前\(8\)位唯一確定,每次只需要預處理後\(8\)位的結果。

時間複雜度還是\(o(2^8)\)

總的複雜度還是\(o(2^8)\)

求乙個數約數的個數

求約數的個數 計算乙個整數的約數個數 輸入格式 輸入乙個整數 輸出格式 輸出一行,為輸入整數的約數的個數 樣例輸入 10 樣例輸出 4ac import math number int raw input count 0 sqrt float math.sqrt number if number s...

位與 乙個數 1的結果

在計算機中,位與的符號是 運算過程是false false false,true false false,true true true 故任何乙個數 1的結果有 0 1 0 1 1 1 2 1 0 3 1 1 1234 1 0 4321 1 1 可以看出乙個奇數 十進位制 位與1的結果是1,乙個偶數...

求乙個數中1的個數

碰到遇到乙個有趣的題,求乙個數二進位制的表示中1的個數,該題有兩種解法,一種是使用短除法將該數直接轉化為二進位制數,另一種比較巧妙的演算法是使用與運算,原理如下圖所示 依照此種思入有如下演算法 int numberof1 solution3 int i return count 依照短處法的思路 有...