N0lP 2018 貨幣システム#
一週間もかからずにこれを書いたの?
問題#
貨幣の種類は $n$、額面の配列は $a [1..n]$ の貨幣システムを $(n,a)$ と表します。
2 つの貨幣システム $(n,a)$ と $(m,b)$ が等価であるとは、任意の非負整数 $x$ に対して、それが 2 つの貨幣システムのいずれかで表されるかどうかが同じであることです。
貨幣システム $(n,a)$ と等価で、かつ $m$ ができるだけ小さい貨幣システム $(m,b)$ を見つけてください。
最小の $m$ を出力してください。
解法#
ある貨幣システムの中のいくつかの貨幣が他の貨幣で表される場合、それらを取り除くことができます。
したがって、まずソートし、それぞれの a[i]
について、それを表すことができるとマークします。
そして、完全背包のアイデアを使って選別します(満たされることができる貨幣をマークします)
コード#
#include <cstdio>
#include <algorithm>
using std::max;
using std::sort;
const int MAXN = 105, MAXA = 25000;
int main (void) {
int T;
scanf("%d", &T);
while (T--) {
int a[MAXN] = {0};
bool v[MAXA] = {0};
int n, maxa = 0, ans = 0;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
maxa = max(maxa, a[i]);
}
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; ++i) {
if (v[a[i]]) continue;
++ans;
v[a[i]] = 1;
for (int j = a[i]; j <= maxa; ++j) {
if (v[j - a[i]]) v[j] = 1;
}
}
printf("%d\n", ans);
}
return 0;
}