bzoj3233 [Ahoi2013]找硬币
那么第i个数
那么对于一个价格为n的物品第
所以我们可以考虑dp,f[i]表示最后一个数为,然后除了i以外前面的数的最小的硬币数量是多少.
#include<cstdio>
#include<algorithm>
#include<cstring>
const int N = 100005;
int f[N], n, a[51], ret;
void G (int &num) {
static char a; static bool fl;
for (a = getchar (), fl = false; a > '9' || a < '0'; a = getchar ()) if (a == '-') fl = true;
for (num = 0; a >= '0' && a <= '9'; a = getchar ()) num = (num << 3) + (num << 1) + a - '0';
if (fl) num = -num;
}
void Min (int &x, int y) { if (x > y) x = y; }
int main () {
// freopen ("3233.in", "r", stdin);
int S = 0;
G (n);
for (int i = 1; i <= n; ++i) G (a[i]);
std :: sort (a + 1, a + n + 1); S = a[n];
memset (f, 0x3f, sizeof f);
f[1] = 0;
for (int i = 1; i <= S; ++i) {
for (int j = 2; i * j <= S; ++j) {
ret = 0;
int &tx = f[i * j];
for (int k = n; k; --k) {
ret += a[k] / i % j;
if (f[i] + ret > tx) break;
}
Min (tx, f[i] + ret);
}
}
int ans = 0x3f3f3f3f;
for (int i = 1; i <= S; ++i) {
ret = 0;
for (int k = 1; k <= n; ++k) ret += a[k] / i;
f[i] += ret;
if (ans > f[i]) ans = f[i];
}
printf ("%d\n", ans);
return 0;
}