Bits Reverse(貪心 位運算)

2022-06-08 15:48:12 字數 2370 閱讀 9718

給定兩個非負整數\(x\)和\(y\)。

規定一種操作,逆序任意三個相鄰的二進位制位。

問最少需要多少次操作,能使得\(x = y\)。若不能達到,則輸出\(-1\)。

\(1 \leq t \leq 10000\)

\(0 \leq x, y \leq 10^\)

我們先觀察一下這個逆序操作有什麼性質,假設三個相鄰的二進位制位構成乙個三元組\((a, b, c)\),逆序之後變為了\((c, b, a)\)。

可以發現,中間的二進位制數不變,兩端的數字交換。因此乙個很自然的思路就是將\(x\)和\(y\)分別轉換成二進位制形式,然後奇偶分別考慮。

另乙個性質是,任意奇數字之間都可以交換,任意偶數字之間也可以交換。

另外需要考慮的一點是,最後使得\(x = y\),我們可以假定\(y\)不變,令\(x\)變向\(y\)。因為\(y\)的一次操作對應\(x\)的一次操作。

第一問,能不能達到\(x = y\),這個可以通過分別計算\(x\)和\(y\)中奇數字\(1\)的個數是否相等,偶數字\(1\)的個數是否相等來判斷。

第二問,最少需要多少步,這個需要思考乙個貪心策略。以奇數字為例進行思考(偶數字同理),從低位到高位,將\(x\)與\(y\)每一位進行比對。若第\(j\)個奇數字不同,則往高位尋找第乙個滿足下列條件奇數字\(k\),有\(x_k = y_j\),且\(k > j\),然後交換\(x\)的第\(j\)個奇數字和第\(k\)個奇數字,這需要\(k - j\)步。

這裡給出乙個簡短的證明,假定\(1 \dots j - 1\)個奇數字\(x\)與\(y\)相同,而第\(j\)個奇數字不同,那麼我們必然需要從高位找乙個奇數字\(k\)來交換到第\(j\)位,假定用\(k'\)時步數最少,需要\(k' - j\)步。而,按照之前的策略,將\(k\)位交換\(j\)位,然後我們可以再將交換後的\(k\)位(即原來的\(j\)位)與\(k'\)位交換,這樣總步數也是\(k' - j\)步。這說明我們的策略不差於最優策略。得證!

這種做法的時間複雜度是\(o(34^2t)\),時間是允許的,但是考慮乙個優化。我們可以先預處理出\(x\)和\(y\)的所有奇數字中\(1\)的位置(偶數字同理),計算\(\sum (x_i - y_i)\),正確性顯然。這樣時間複雜度是\(o(34t)\)。

#include #include #include #include using namespace std;

typedef long long ll;

const int n = 100;

int a[n], b[n];

int cnt1, cnt2;

int main()

for(int j = 0; j < 100; j ++)

int ans = 0;

cnt1 = cnt2 = 0;

for(int j = 0; j < 100; j += 2)

if(cnt1 != cnt2)

for(int j = 0; j < 100; j += 2) }}

cnt1 = cnt2 = 0;

for(int j = 1; j < 100; j += 2)

if(cnt1 != cnt2)

for(int j = 1; j < 100; j += 2) }}

printf("case %d: %d\n", i, ans);

}return 0;

}

#include #include #include #include using namespace std;

typedef long long ll;

const int n = 100;

int a[n], b[n];

int cnt1, cnt2;

int loc1[n], loc2[n];

int main()

for(int j = 0; j < 100; j ++)

int ans = 0;

cnt1 = cnt2 = 0;

for(int j = 0; j < 100; j += 2)

if(cnt1 != cnt2)

for(int j = 0; j < cnt1; j ++) ans += abs(loc1[j] - loc2[j]) / 2;

cnt1 = cnt2 = 0;

for(int j = 1; j < 100; j += 2)

if(cnt1 != cnt2)

for(int j = 0; j < cnt1; j ++) ans += abs(loc1[j] - loc2[j]) / 2;

printf("case %d: %d\n", i, ans);

}return 0;

}

1134 整數去位 貪心

題目描述 鍵盤輸入乙個高精度的正整數n,去掉其中任意m個數字後剩下的數字按原左右次序將組成乙個新的正整數。程式設計對給定的n和m尋找一種方案使得剩下的數字組成的新數最小。輸出組成的新的正整數。輸入資料均不需判錯。如果去掉了某幾個位後得到的新整數開頭為0,保留0。輸入 505 1 輸出 05 輸入第一...

小A的位運算 貪心

題目描述 位運算是乙個非常重要的東西。而小a最近在學習位運算,小a看到了一道很簡單的例題,是說從n個數裡面選出n 1個數要讓它們或起來的值最大,小a想知道這個答案是多少。你可以幫幫他嗎?兩種方法 1.可以用貪心的思路,從大到小依次去更新或值ans,如果或到乙個數沒改變時,說明至少可以不選它,如果一直...

《Thinking in java》基礎篇之位運算

分類 在計算機中所有資料都是以二進位制的形式儲存的。位運算其實就是直接對在記憶體中的二進位制資料進行操作,因此處理資料的速度非常快。符號位 二進位制數最高位表示符號位,0表示正數,1表示負數。原碼 整數的二進位制數。反碼 符號位不變,其餘部分取反。補碼 原碼取反 1,符號位不變。或者說反碼 1,符號...