1. 程式人生 > 其它 >Codeforces Round #781 (Div. 2)

Codeforces Round #781 (Div. 2)

比賽連結

A. GCD vs LCM

1, n - 3, 1, 1

B. Array Cloning Technique

首先,最後全部相等的元素,肯定是選初始時出現次數最多的元素,記該元素為\(x\),其出現次數為\(c\)

然後每次複製,都是新的拷貝中,所有的\(x\)都拷回原陣列。這裡,易得把數拷回原陣列的操作共有\(n - c\)次,然後只剩拷貝的操作了。

第一次複製出來的陣列中包含\(c\)\(x\),第二次包含\(2c\)個,第三次包含\(4c\)個,以此類推。

然後模擬一下就好了。

C. Tree Infection

首先,這題只和每個節點的子節點個數有關,將所有非葉子節點的兒子個數記錄下來,注意還有根節點也要算1次。

然後,先infect的點後續可以藉助spread白嫖,所以排個序,貪心先搞兒子個數多的。

然後求最小值就跑個二分。

注意每次spread只能搞一個,就算這個集合中被多次infect了。

D. GCD Guess

比賽的時候就差最後一步沒想明白,錯失上分機會。

首先,從低位開始,每次確定\(x\)的一個位,這樣是可以在30輪內完成的。

對於第\(1\)輪,\(a=2,b=4\)\(gcd(x+a, x+b) = gcd(x+a, b - a) = gcd(x + a, 2)\),如果返回結果為\(2\)說明\(x\)最低一位為0,反之為1。

對於第\(i\)輪,\(x\)的低\(i - 1\)位已經確定了,現在要確定其第\(i\)

位。令\(a = 2^i - (x \mod 2^i)\)\(b = a + 2^i\)\(gcd(x+a,x+b) = gcd(x + a, b -a) = gcd(x + a, 2^i)\),如果返回結果為\(2^i\)說明\(x\)\(i\)位為0,反之為1。

但是這個做法在最後一輪的時候會因為\(b\)超過\(10^9\)掛掉,所以需要特判。

本來想著用\(gcd(2x,3x) = x\)來判斷,但是發現\(3x\)會超出\(10^9\),所以改用\(gcd(x + 1, 2x + 2) = x+1\)來判斷。

E. MinimizOR

可以證明,區間\([l, r]\)的答案,一定是在其中最小的\(31\)

個值數產生,找到區間最小的31個數,列舉兩兩或的結果,取最小值即為答案。

區間最小值可以想到線段樹,然後最小的31個數可以每次取完最小就將對應位置改為無窮大,這樣通過31次取最小和單點修改操作就可以獲取最小的31個數,然後算完結果再恢復回去。

證明

命題:如果區間內最大值小於\(2^k\),那麼區間內的答案一定是在其中最小的\(k+1\)個數中產生。

可以用歸納法證明。

  • \(k=1\)的時候顯然成立。

  • 假設對於\(k\)成立,則對於\(k+1\)

    • 如果區間內的數,第\(k+1\)位全為1,那麼答案的第\(k +1\)位為1。答案和只考慮後\(k\)位一樣,結論成立。
    • 如果區間內的數,有大於等於2個第\(k+1\)位為0,那麼答案的第\(k+1\)為為0。此時我們只需要考慮第\(k+1\)位為0的數,前\(k\)位小的數前面加上0還是小,所以結果還是會在之前選出來的最小值中,結論成立。
    • 如果區間內的數,只有1個第\(k+1\)位為0,那麼答案的第\(k +1\)位為1。此時,之前的候選可能和這個第\(k+1\)位為0的數產生新的答案,所以將其加入最小值集合,現在是\(k+2\)個最小值,結論依然成立。