小 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...