3342 NOI2020 製作菜品

2022-09-17 00:33:11 字數 1216 閱讀 1273

題目鏈結

考場上想到 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 的部分分,考慮從這裡切入分...