Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

N0lP 2018 货币系统

划水一周就写了个这玩意儿?

题目

传送门

货币种数为 nn、面额数组为 a[1..n]a[1..n]的货币系统记作 (n,a)(n,a)

两个货币系统$ (n,a)$ 和$ (m,b)是等价的,当且仅当对于任意非负整数是等价的,当且仅当对于任意非负整数x$,它要么均可以被两个货币系统表出,要么不能被其中任何一个表出。

找到一个货币系统 (m,b)(m,b),满足 (m,b)(m,b)与原来的货币系统 (n,a)(n,a)等价,且 mm尽可能的小。

输出最小的mm

解法

如果一个货币系统里的某些货币能被另一些货币表示,那么就可以踢掉。

所以,先排序,然后对每一个a[i],把它标记为可以被表示,

再利用完全背包的思想来筛(把能被填满的货币标记)

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#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;
}

评论