zoukankan      html  css  js  c++  java
  • 【BZOJ 3233】 [Ahoi2013]找硬币

    【题目 描述】

    小蛇是金融部部长。 最近她决定制造一系列新的货币。 假设她要制造的货币 的面值为 x1, x2, x3… 那么 x1 必须为 1, xb 必须为 xa 的正整数倍(b>a)。 例如 1, 5, 125, 250 就是一组合法的硬币序列, 而 1, 5, 100, 125 就不是。 不知从哪一天开始, 可爱的蛇爱上了一种萌物——兔子! 从此, 小蛇便走上 了遇上兔子娃娃就买的不归路。 某天, 小蛇看到了 N 只可爱的兔子, 假设这 N 只 兔子的价钱分别是 a1, a2…aN。 现在小蛇想知道, 在哪一组合法的硬币序列下, 买这 N 只兔子所需要的硬币数最少。 买兔子时不能找零。

    【输入格式】

    第一行, 一个整数 N, 表示兔子的个数 第二行, N 个用空格隔开的整数, 分别为 N 只兔子的价钱

    【输出格式】

    一行, 一个整数, 表示最少付的钱币数。

    【样例输入】

    2

    25 102

    【样例输出】

    4

     【样例解释】

    本次比赛试题由厦门一中提供 共有两只兔子, 价钱分别为 25 和 102。 现在小蛇构造 1, 25, 100 这样一组 硬币序列, 那么付第一只兔子只需要一个面值为 25 的硬币, 第二只兔子需要一 个面值为 100 的硬币和两个面值为 1 的硬币, 总共两只兔子需要付 4 个硬币。 这 也是所有方案中最少所需要付的硬币数。

    【数据范围与约定】

    对于 20%的数据, 1<=N<=20, 1<=ai<=5, 000

    对于 100%的数据, 1<=N<=50, 1<=ai<=100, 000 部分数据随机.




    一道不错的动态规划,考试的时候完全完全没有思路呢。

    先考虑DP数组 f[i] 表示此时硬币面额的最大值为i时,买所有小兔纸所用的最少硬币,显然边界的 f[1]=∑1n ai

    然后是转移。

    f[i*j]=min(f[i*j],f[i]-ts[i*j]*(j-1)) (SMG??)

    首先i和j都是数字i*j的因子咯,所以一个面值为i*j的硬币相当于j个面值为i的硬币,即j个i硬币可以变成  1 个i*j硬币,所以硬币数量就会减少 (j-1) 个啦。

    然后ts数组里存的是i*j这个硬币最多可以用几次,就是 Sigma{a[k]/(i-j)} (打Sigma好辛苦

    具体看代码吧(并没有很长)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 
     7 #define For(i,a,b) for(register int i=a;i<=b;++i)
     8 #define Re register
     9 #define inf 0x7f7f7f
    10 using namespace std;
    11 const int N=55,MN=1e5+10;
    12 int a[N],ts[MN],f[MN];
    13 int n,mx=0,fn;
    14 inline void read(int &v){
    15     v=0;
    16     char c=getchar();
    17     while(c<'0'||c>'9')c=getchar();
    18     while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar();
    19 }
    20 int main(){
    21 //    freopen("coin.in","r",stdin);
    22 //    freopen("coin.out","w",stdout);
    23     read(n);
    24     memset(f,inf,sizeof(f));
    25     For(i,1,n) read(a[i]),mx=max(a[i],mx);
    26     For(i,1,mx) For(j,1,n) ts[i]+=a[j]/i;
    27     fn=ts[1]; f[1]=ts[1];
    28     For(i,1,mx){
    29         fn=min(fn,f[i]);
    30         for(Re int j=1;j*i<=mx;++j){
    31             f[i*j]=min(f[i*j],f[i]-ts[i*j]*(j-1));
    32         }
    33     }
    34     cout<<fn<<endl;
    35     return 0;
    36 }
  • 相关阅读:
    Web前段学习索引
    Python学习索引
    Centos7下安装Docker(详细的新手教程)
    Django部署阿里云服务器(nginx+uwsgi)
    (转)Mongo db 与mysql 语法比较
    (转)mongo基本常用命令
    python操作mongodb的基本操作命令
    http响应码
    python回调函数
    Flask框架的使用
  • 原文地址:https://www.cnblogs.com/HLAUV/p/9880318.html
Copyright © 2011-2022 走看看