P5514 MtOI2019 永夜的報應 題解

2022-02-14 15:59:10 字數 1344 閱讀 3674

csdn同步

原題鏈結

簡要題意:

給定乙個長度為 \(n\) 的序列 \(a\),你需要將其分為若干組,使得每一組的異或之和最小。求這個最小值。

實際上這題是個結論題。

先考慮乙個問題:對於乙個數 \(x\),唯一的一組 \(s\),你會選擇將 \(x\) 單分一組還是加入 \(s\) 呢?

由於異或的結合律,所以我們可以抽象地假設一手,設 \(s\) 中所有元素的異或值為 \(m\).

這個問題就變成了,\(x+m\) 和 \(x \oplus m\),哪個小?

再抽象一手,\(a+b\) 和 \(a \oplus b\),哪個小?

你的直覺可能是 \(a \oplus b\) 小。最好我們還是證明一下。

假設 \(a>b\) 且 \(a\) 化為二進位制後共 \(k\) 位。

對於任意的第 \(i (1 \leq i \leq k)\) 位,存在:

\(0 \oplus 0 = 0 , 0 + 0 = 0\).

\(0 \oplus 1 = 1 , 0 + 1 = 1\).

\(1 \oplus 1 = 0 , 1 + 1 = 10\).(進製)

這樣你就會發現 \(a \oplus b \leq a + b\).

當然如果理論上的證明不夠愉快,可以來一手感性證明。

異或本質是不進製的加法,加法是進製的加法

這樣只要存在進製,異或就會比加法的結果小。否則相等。

回歸剛才的那個問題:

對於乙個數 \(x\),唯一的一組 \(s\),你會選擇將 \(x\) 單分一組還是加入 \(s\) 呢?

顯然答案水落石出,就是加入 \(s\).

這樣整個問題的答案就出來了,\(\text_^n a_i\) 即為答案。

時間複雜度:\(\mathcal(n)\).

實際得分:\(100pts\).

#pragma gcc optimize(2)

#includeusing namespace std;

inline int read()

int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}

inline void write(int x)

if(x<10)

write(x/10);putchar(char(x%10+'0'));

}int main()

時間跳躍,MtOI2019,Dp

portal 很容易想到如果最小k 1條邊之和 最大那條邊,那麼就可以構成乙個k邊形。否則顯然構不成乙個多邊形。那麼很容易可以想到dp 發現並不需要記下那麼多東西,用 轉移的時候也是很容易的。那麼就相當於做01揹包,然後順便預處理一下字首和就可以了。選出乙個子集代價為自己大小的總和為 居然沒想到這種...

P5514 永夜的報應(異或,數學)

p5514 永夜的報應 做kruskal重構樹膩了,來拓展下視野。定義一組數的權值為該組內所有數的異或和.請求出一種分組方案,使得分出的所有組數的權值之和最小,輸出權值之和的最小值.我們知道異或運算的基本法則 同號則為假,異號則為真.不妨對每一位進行分析 0 0 0 1 0 0 1 1 1 1 0可...

P5468 P6302 NOI2019 回家路線

原題p5468,洛谷加強版p6302,loj3156 聽說原題是用腳造的資料,所以可能無法把 的鍋都測出來,所以還是去加強版吧 做了好長時間,主要是原版得分玄學,有的時候把 乙個地方改錯甚至得了更多的分 當時同時還存在其它的錯 jk,然後加強版又被卡常 kk 斜率優化dp vector 維護凸包 堆...