7
通讀題解之後決定把能看懂的題目補了(畢竟能看懂的也不多,某些演算法聽都沒聽過 QwQ)
A Maximum Subarray Sum (A)
(出題人解法沒看明白)
解法2的切入點類似之前某場div2的D題(題解傳送門),將操作過程視為選出 \(\lfloor n/k\rfloor\) 個長度為 \(k\) 的子序列,答案序列中大於 \(k\) 的部分暫時與捨棄部分等價,即最後捨棄的數字下標滿足 \(i' = i\space mod\space k\). 設 \(dp[i][x][y][p]\) 表示到 \(i\) 位置,換走 \(x\) 個數、換入 \(y\) 個數,當前選擇狀態為 \(z\)(選或不選)時的最大和,每個計入答案的數可能存在按序選入/中途換入兩種選擇方式,同理未計入答案的數也存在直接拋棄/換出兩種可能。當前數被選中時,由於子序列長度至少為 \(k\),為避免出現間斷點,\(dp[i][x][y][1]\) 只能由 \(dp[i - k + 1][x][y][1]\)(長度為 \(k\) 的子序列)或 \(dp[i - 1][x][y][1]\)(答案序列中大於 \(k\) 的部分)轉移而來,前者需要從 \(0\) 到 \(m\) 列舉換出數字的數量,其他所有情況則可以 \(O(1)\) 轉移。利用字首和與set之類的容器處理換出後的序列最大值,整體複雜度可最佳化至 \(nm^3\) 左右。特別地,當 \(i\space mod\space k = k - 1\) 時,由於捨棄的數不可能超過 \(k - 1\) 個,該位置上的數字不能被直接拋棄,只進入 \(0\) 至 \(m\) 的迴圈、討論可能存在的換出情況。程式碼還是借鑑其他隊答案才寫明白的,所以沒放這裡了 TAT
I Fight Against the Monster (I)
題解思路是二分答案,不過不用二分也行。\(h\leq m\) 時顯然答案為 \(h\),對於 \(h > m\) 的情況,若生產出的 \(k\) 臺新機器仍不足以將怪物殺死,可以選擇直接補充與剩餘血量相等的機器數目(\(h'\leq m - k\) 時),或補充 \(m - k\) 臺機器至恰好足以生產新機器,依此思路可 \(O(1)\) 計算答案,程式碼如下:
if(h <= m) printf("%lld\n", h);
else if(m <= k) printf("%lld\n", m);
else {
ll sum = h - m;
if(sum <= k) printf("%lld\n", m);
else {
ll cnt = sum / m, x = sum % m;
if(x >= k) printf("%lld\n", m + cnt * (m - k) + (x - k));
else printf("%lld\n", m + cnt * (m - k));
}
}
8
上週四不在家所以沒打,後來自己寫的時候各種卡題,難過)
A Haitang and Game (A)
事實上A題並不是一道博弈題,最終序列中加入的所有 \(d\) 是固定的,不存在任何可能改變勝負的博弈策略。具體而言,若序列中 \(d\)(本身不存在於序列中)的倍數有 \(a_i,a_j,...\),且 \(gcd(a_i,a_j,...) = d\),則 \(d\) 必然會被加入。資料範圍 \(a_i\leq 10^5\),遍歷 \(1\) 至 \(a_{max}\),列舉倍數判斷其是否為合法的 \(d\),由調和級數得整體複雜度 \(nloga_{max}\).