• Bzoj3233 [Ahoi2013]找硬币


    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 804  Solved: 408

    Description

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

    Input

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

    Output

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

     

    Sample Input

    2
    25 102

    Sample Output

    4

    HINT


    样例解释:共有两只兔纸,价钱分别为25和102。现在小蛇构造1,25,100这样一组硬币序列,那么付第一只兔纸只需要一个面值为25的硬币,第二只兔纸需要一个面值为100的硬币和两个面值为1的硬币,总共两只兔纸需要付4个硬币。这也是所有方案中最少所需要付的硬币数。

       1<=N<=50, 1<=ai<=100,000

    Source

    动态规划 刷表DP 脑洞题

    题目令人十分迷茫,看了题解以后忍不住想大呼“还有这种操作”

    会这么想的绝对只有我一个人

    设$ f[i] $表示把“用面值为i的硬币付不掉的那部分”干掉 (也就是清除“边角料”)的最小花费。

    设$ g[i] $表示最多可以使用的面值为i的硬币的数量(因为硬币面值都是倍数关系,所以能用大的肯定先用大的)。

    显然这两个是互补的。

    那么显然 ans = min{ f[i] + g[i] }

    对于每个i,枚举i的质数倍,有转移:

      $f[ prime[j] * i ] = min ( f[ prime[j] * i , f[i] + calc(i , k) )$

    这个calc(i,k)是将用k不能解决的部分用i解决所需的硬币i的个数。具体统计方式见代码。

    注意除法是整除。

    那么问题来了,用i去支付的时候,i不能解决的部分是不是因为整除而漏算了呢?并没有,这部分被统计在f[i]里了

    会在这个地方转不过弯的绝对只有我一个人

    预处理一下质数,就可以愉快地解决了

    因为看着和线性筛有些像,于是试着加了57行那个break,然而是错的2333

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 using namespace std;
     7 const int N=100010;
     8 const int mxn=60;
     9 int read(){
    10     int x=0,f=1;char ch=getchar();
    11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 int n,a[mxn];
    16 int mx;
    17 int pri[N],cnt=0;
    18 bool vis[N];
    19 int f[N];
    20 void init(){
    21     for(int i=2;i<=mx;i++){
    22         if(!vis[i]){
    23             pri[++cnt]=i;
    24         }
    25         for(int j=1;j<=cnt && pri[j]*i<=mx;i++){
    26             vis[pri[j]*i]=1;
    27             if(i%pri[j]==0)break;
    28         }
    29     }
    30     return;
    31 }
    32 int calc(int x,int mod){
    33     int res=0;
    34     if(!mod){
    35         for(int i=1;i<=n;i++)
    36             res+=a[i]/x;
    37         return res;
    38     }
    39     for(int i=1;i<=n;i++)
    40         res+=a[i]%mod/x;
    41     return res;
    42 }
    43 int main(){
    44     int i,j,k;
    45     n=read();
    46     for(i=1;i<=n;i++)a[i]=read(),mx=max(mx,a[i]);
    47     init();
    48     sort(a+1,a+n+1);
    49     memset(f,0x3f,sizeof f);
    50     f[1]=0;
    51     int ans=0x3f3f3f3f;
    52     for(i=1;i<=mx;i++){
    53         ans=min(ans,f[i]+calc(i,0));
    54         for(j=1;j<=cnt && ((k=pri[j]*i)<=mx);j++){
    55             f[k]=min(f[k],f[i]+calc(i,k));
    56 //            printf("i:%d k:%d fi:%d fk:%d
    ",i,k,f[i],f[k]);
    57 //            if(i%pri[j]==0)break; //WA
    58         }
    59     }
    60     printf("%d
    ",ans);
    61     return 0;
    62 }
  • 相关阅读:
    C#无限分级实现,前端WEB页面接收,后台提供层级Json数据
    消息队列、OSS常用操作封装
    ABP增删改查代码片段
    WebApi实现验证授权Token,WebApi生成文档等
    项目收集-AutoMapper使用,事务,Json.Net序列化反序列化,代码生成调用等
    ssi服务器端指令详解(shtml)
    Linq常用List操作总结,ForEach、分页、交并集、去重、SelectMany等
    81.Search in Rotated Sorted Array II---二分变形
    48.Rotate Image
    89.Gray Code
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/7067428.html
Copyright © 2020-2023  润新知