哎,被卡科技了,想了三個小時,最後還是大佬給我說是\(sg\)函式。
\(sg\)函式,用起來很簡單,證明呢?(不可能的,這輩子都是不可能的)
遊戲的\(sg\)函式就是各個子遊戲的\(sg\)函式的\(nim-sum\)(就是異或和),比如多堆石子的\(sg\)函式就是所有單堆石子\(sg\)函式的異或和。
首先定義\(mex(t)\)為\(t\)中未出現的自然數中最小的數,其中\(t \subset n\),如\(mex(0,2,3)=1\),\(mex(4,7)=0\)。那麼\(sg(x)=mex(s)\),\(s\)為\(x\)的後繼狀態的\(sg\)函式值集合。
然後,對於某乙個狀態\(x\),若\(sg(x)=0\),則先手必敗,否則先手必勝。
對於這一道題,因為只能拿約數個,也就是至少拿乙個,所以我們可以先從小到大預處理一下\(sg\)函式。然後因為我們是先手,要給對手製造乙個必敗狀態,所以只要列舉一下第一步的所有策略,然後判斷一下剩下的那些石子的\(sg(x)\)函式的異或和是否為\(0\)就行了。
期望複雜度\(o(n^})\)。
#include using namespace std;
const int n = 100000;
int n, a[n+5], sum, p, ans, sg[n+5], vis[n+5];
void calc_sg()
sort(vis+1, vis+cnt+1);
if(vis[1] >= 1)
for(int j = 1; j <= cnt-1; j++)
if(vis[j+1]-vis[j] > 1) t = min(t, vis[j]+1);
t = min(t, vis[cnt]+1);
sg[i] = t;
}} int main()
}cout << ans << endl;
return 0;
}
Wannafly挑戰賽A 概率DP
給你乙個長 n 的序列,m 次查詢 每次查詢給乙個 x,然後 從序列的最左端 1 開始,每次隨機的選擇乙個右端點 r,如果兩個端點間的區間和不超過 x 就進行一次分割,然後把左端點變成 r 1,否則一直隨機下去。問這樣分割出來的期望段數 第一行兩個數 n,m 之後一行 n 個數表示這個序列 之後m行...
Wannafly挑戰賽5 補題
a 珂朵莉與宇宙 思路 科學暴力 列舉字首和,同時計算字首和裡面可能出現的完全平方數,匹配字首和 與完全平方數的差值是否在之前的字首和出現,出現了幾次就是存在多少個區間,利用的是連續的性質。include using namespace std typedef long long ll const ...
Wannafly挑戰賽6 鎖
106號房間共有n名居民,他們每人有乙個重要度。房間的門上可以裝若干把鎖。假設共有k把鎖,命名為1到k。每把鎖有一種對應的鑰匙,也用1到k表示。鑰匙可以複製並發給任意多個居民。每個106房間的居民持有若干鑰匙,也就是1到k的乙個子集。如果幾名居民的鑰匙的並集是1到k,即他們擁有全部鎖的對應鑰匙,他們...