Codeforces ICPC那場

fafatadie發表於2024-11-21

在許多題目中,我原來感覺第二題應該是不難的,結果難的我都不想做了,所以發一下第二題的題解。

題目的意思便是對一個列表,任意選擇範圍內的索引i ,使A[i] -= 2,A[(i+1)%len(A)] += 1,我的第一想法便是用差分,使差分列表全部為零即可,但是操作就變得無規律了

為什麼我會想到用差分呢,因為改變後的列表都為[n]*(len(A)),其中的n我們並不確定,可能是出現次數最多的元素,也可能是其他元素,但對於任意一個正確答案,只有其差分陣列是有規律的,都為【0】乘len(A).


但最後我錯了,先給大家看一下正確的程式碼:

    import sys
    inp = lambda: sys.stdin.readline().rstrip()
    Inp = lambda: [*map(int, sys.stdin.readline().split())]
    from bisect import bisect_left, bisect_right
    from math import gcd
    for _ in range(int(inp())):
        n, = Inp()
        A = Inp()

        C = [0]*n
        i = 1
        for _ in range(30):
            for j in range(n):
                if A[j]&i:
                    C[j] += i
                    A[j] += i
                    A[(j-1)%n] -= 2*i
            i <<= 1
    
        if -min(C) <= min(A) == max(A):
            print(sum(C)-min(C)*n)
        else:
            print(-1)、

接下來解釋一下程式碼:我們先把列表中的每個數字看成二進位制數字,我們要把每個二進位制變為一樣的,有個結論:在二進位制數字中,每次操作都可以看成用高一位的1來換去本位的1,逆向思維,也就相當於用本位的1來換取高一位的1 ,而且大家應該發現了,對每次操作i位置上的1是,操作A[(j-1)%n]這個數字是對這個數字的i位置上的1是沒有影響的,即使A[(j-1)%n]數中的i+1位置上為0,可以用更高位置上的1分解來替換的。
-> 為什麼要取30位的二進位制呢?
**因為30位的二進位制數字可以表示2^30−1=1073741824−1=1073741823,而資料範圍是1e9,完全是可以包含所有數字的。
->還有一個結論,如圖所示:

相關文章