【YBTOJ】【Luogu P5020】[NOIP2018 提高組] 貨幣系統
阿新 • • 發佈:2021-07-08
【YBTOJ】【Luogu P5020】[NOIP2018 提高組] 貨幣系統:
連結:
題目大意:
在網友的國度中共有 \(n\) 種不同面額的貨幣,第 \(i\) 種貨幣的面額為 \(a[i]\),你可以假設每一種貨幣都有無窮多張。為了方便,我們把貨幣種數為 \(n\)、面額陣列為 \(a[1..n]\) 的貨幣系統記作 \((n,a)\)。
在一個完善的貨幣系統中,每一個非負整數的金額 \(x\) 都應該可以被表示出,即對每一個非負整數 \(x\),都存在 \(n\) 個非負整數 \(t[i]\) 滿足 \(a[i] \times t[i]\) 的和為 \(x\)。然而, 在網友的國度中,貨幣系統可能是不完善的,即可能存在金額 \(x\)
兩個貨幣系統 \((n,a)\) 和 \((m,b)\) 是等價的,當且僅當對於任意非負整數 \(x\),它要麼均可以被兩個貨幣系統表出,要麼不能被其中任何一個表出。
現在網友們打算簡化一下貨幣系統。他們希望找到一個貨幣系統 \((m,b)\),滿足 \((m,b)\) 與原來的貨幣系統 \((n,a)\) 等價,且 \(m\) 儘可能的小。他們希望你來協助完成這個艱鉅的任務:找到最小的 \(m\)。
題目大意:
在 \(a\) 中可能有的數會被其它數表示出來,把這些數篩掉就完事了。
程式碼:
inline ll Read() { ll x = 0, f = 1; char c = getchar(); while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') f = -f, c = getchar(); while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * f; } int n, a[N], f[M]; int main() { for (int t = Read(); t--; ) { n = Read(); memset (f, 0, sizeof (f)); for (int i = 1; i <= n; i++) a[i] = Read(); int ans = n; sort (a + 1, a + 1 + n); f[0] = 1; for (int i = 1; i <= n; i++) { if (f[a[i]]) {ans --; continue;} for (int j = a[i]; j <= a[n]; j++) f[j] |= f[j - a[i]]; } printf ("%d\n", ans); } return 0; }