題目鏈結
考場上想到 70pts,結果沒清空+沒特判轉移**丟掉 35pts
不那麼顯然,如果 \(m \ge n - 1\),那麼一定有解。
考慮如果只剩下一堆大於 \(k\) 的材料,那麼每次我們取乙個,不夠再取另乙個,一定能取完。於是我們只用考慮怎麼消滅小於 \(k\) 的材料。因為每次我們可以把最小的那個取走,不夠再從大於 \(k-v_i\) 的那些材料裡面找,每取一次肯定能消滅乙個小的,並且我們能保證能找到大於 \(k-v_i\) 的材料,否則剩下的平均將小於 \(k-v_i\),仔細想想發現 \(m \ge n - 1\) 的時候不可能。因此我們能夠在 \(m \ge n - 1\) 的情況下找到解。
現在考慮 \(m = n - 2\)。如果有解,一定時拿著拿著發現正好有兩個的和為 \(k\),一下子消掉兩個。換言之,我們能夠將原材料分成兩個集合,對於每個集合都符合 \(\sum_ v_i = (|s| - 1) * k\) 的性質。那麼我們直接揹包 dp 即可拿到 70pts。
發現我們要記乙個集合大小,很不方便。我們可以統一讓 \(v_i\) 減去 \(k\),最後判斷是否可能為 \(-k\) 即可。
發現我們的 dp 狀態設成布林型別肯定不好,並且發現每次就是對陣列進行左移和或操作,因此直接上 bitset 優化即可。因為我們要知道轉移路徑,因此不能滾動陣列,但是在 bitset 的強力優化下還是可行的(dp陣列大概有幾千萬位元組)。不過絕對不能記錄 \(pre\),要當場手動模擬,看如果選擇 \(cur\) 之前的狀態是否合法,據此決定是否選擇 \(cur\)。
關鍵**:
bool vis[567];
inline void get_ans() ;
vis[stk[i]] = true;
} sol(stop, stop - 1);
int ntot = 0;
for (register int i = 1; i <= n; ++i) ;
} sol(ntot, ntot - 1);
success();
}bitsetbt[505];
inline bool try()
if (!bt[n][-k + base]) return false;
int nw = -k;
for (register int i = n; i; --i)
} return true;
}
LOJ3342 NOI2020 製作菜品
題目鏈結 博主有幸參加了noi2020,考場上的經歷和心得請見這篇文章。這裡就不嘮叨了。本題的突破口在於 m 和 n 的關係。也就是資料範圍表裡這些奇怪的限制 m n 1 m geq n 1 m geq n 2 我們乙個乙個來看。顯然,n 種原材料,除了在輸出答案時,其他時候它們的原始順序對我們解題...
NOI 2020 製作菜品 揹包dp
觀察資料範圍可以發現 m n 1,m n 2,m geq n 是三個比較特殊的資料點,那麼就找這三個點的規律 懶得寫了,直接放 zhq 的 luogu blog 了 然後就只剩下 m n 2 了,還是懶得寫了.原來是記 dp i j k 表示前 i 個選 j 個和為 k 的方案數,可以通過柿子轉換 ...
NOI2020 製作菜品 題解
題意分析 給出 n 個數和 m 個 k 可以某些 k 拆兩個正整數,使得拆後的數可以拼成給出的 n 個數。思路分析 上面的解釋是因為這樣寫比較方便,實際上按照題意應該是用 n 個數拆分拼成 m 個 k 觀察資料範圍,發現有 m geq n 2 的限制和 m geq n 1 的部分分,考慮從這裡切入分...