這是乙個聽來的神仙東西。
先確定一下值域把,大概\(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 依照短處法的思路 有...