您好,欢迎来到汇智旅游网。
搜索
您的当前位置:首页bzoj3233 [Ahoi2013]找硬币

bzoj3233 [Ahoi2013]找硬币

来源:汇智旅游网

a[i] 表示第i个数是第i-1个数的多少倍 a[1]=1
那么第i个数 b[i]=ij=1a[j]
那么对于一个价格为n的物品第 i 个数用的次数nb[i]%a[i+1]
所以我们可以考虑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;
}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- hzar.cn 版权所有 赣ICP备2024042791号-5

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务