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 維護凸包 堆...