習題 選數(tri樹)

2022-07-09 23:45:16 字數 1468 閱讀 5539

小 s 要在 \([0,2^n)\) 中選乙個整數 \(x\),接著把 \(x\) 依次異或 \(m\) 個整數 \(a_1 \sim a_m\),他想要最大化 \(x\) 的最終取值。

然而問題並沒有這麼簡單,小 r 想要干預小 s 的選擇。

在小 s 選出 \(x\) 後,小 r 會選擇恰好乙個時刻(剛選完數時、異或一些數後或是最後),將 \(x\) 變為 \((\lfloor \frac \rfloor +2x) \bmod 2^n\)。

小 s 想使 \(x\) 最後盡量大,而小 r 會使 \(x\) 最後盡量小。

小 s 想要求出 \(x\) 最後的最大值,以及得到最大值的初值數量。

然而小 s 太笨了不會算,請你幫幫他。

對於 \(20\%\) 的資料,\(n \leq 10,m \leq 100\);

對於 \(40\%\) 的資料,\(n \leq 10,m \leq 1000\);

對於另外 \(20\%\) 的資料,\(n \leq 30,m \leq 10\);

對於 \(100\%\) 的資料,\(n \leq 30,m \leq 100000,0 \leq a_i<2^n\)。

設\(f(x)=(\lfloor\frac+2x\rfloor)\% 2^n\)

可以發現,這就是對x進行一次向左的迴圈

考慮乙個數\(x\),他會進行的變化為\(f(x\oplus pre_i)\oplus(pre_n\oplus pre_i)\)

其中\(pre_i\)表示字首異或

有了對\(f(x)\)的深入理解,發現\(f\)可以拆開

\(f(x)\oplus f(pre_i)\oplus(pre_n\oplus pre_i)\)

可以發現\(f(x)\)對先手而言沒有用

可以轉換為\(x\oplus f(pre_i)\oplus(pre_n\oplus pre_i)\)

之後考慮\(f(pre_i)\oplus (pre_n\oplus pre_i)\)進行建tri樹

對於每乙個節點先手的選擇就是\((0,1)\),後手的選擇就是左兒子和右兒子

如果有兩個兒子,那麼不管怎麼樣都為0,所以需要兩邊都去搜尋

只有乙個兒子,就可以構造成為1

#include#includeusing namespace std;

#define pii pair#define x first

#define y second

namespace tri

tre[30*100000+5];

void insert(int s)

}pii ask(int now,int ans)

/*for(int i=1;i<=m;i++)

cout

for(int i=0;i<=m;i++)

pii t=ask(1,0);

cout

}

樹之習題選講

核心演算法 void solve int prel,int inl,int postl,int n root pre prel post postl n 1 root for i 0 i in inl 1 root break l i r n l 1 solve prel 1,inl,postl,l...

unsigned int數相減時候的trick

假設是8位的unsigned int整數。乙個是x 134,乙個是y 246.首先拿過來就是計算它們的二進位制位 134 1000,0110b 246 1111,0110b 因為是無符號數,所以解釋成正數,也就意味著這樣的看似原碼的二進位制位就是補碼表示,也可以理解為符號位在第九位藏著乙個0.這裡主...

選數 題目 1025

已知 nn 個整數 x1,x2,xnx1,x2,xn,以及乙個整數 k k n k k n 從 nn 個整數中任選 kk 個整數相加,可分別得到一系列的和。例如當 n 4,k 3n 4,k 3 4 個整數分別為 3,7,12,19 時,可得全部的組合與它們的和為 3 7 12 22 3 7 19 2...