找硬币题解

问题 A: 找硬币

时间限制: 1 Sec  内存限制: 64 MB

题目描述

小蛇是金融部部长。最近她决定制造一系列新的货币。假设她要制造的货币的面值为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个硬币。这也是所有方案中最少所需要付的硬币数。



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

 

  这道题当时目测是一道数学+搜索或数学+DP题,然后默默地只打了28分。

  这道题我用的是搜索A的,但正解是DP(我竟然都猜对了,不过貌似还没有搜索快),首先一个数一定可以被分解为若干个素数的积,我们可以利用这点只去枚举素数这样能方便不少。指针恒说这道题实际就是一个秦九昭,还真是。

  我们可以得知a[i]=k[2]*x+a[i]%k[2],x为某一个常数,a[i]%b就是需要拿一块钱去补的硬币数。

  然后我们又可知a[i]-a[i]%k[2]=k[2]*x=k[3]*xx+k[2]*x%k[3]……由此我们就可以利用这点去放心大胆的去DFS第j步的余数就是使用k[j-1]的张数。什么时候被排序后的最大的a[1]为0或1了找一下就好了,至于剪枝,传统做法。

  

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<queue>
 6 #include<algorithm>
 7 #include<cmath>
 8 #define N 1000005
 9 using namespace std;
10 int n;
11 int a[55];
12 int bj(int a,int b){
13     return a>b;
14 }
15 bool fss[N];
16 int zz;
17 int ss[N];
18 void xs(){
19     int mx=a[1];
20     for(int i=2;i<=mx;i++)
21     {
22         if(!fss[i])
23         {
24             zz++;
25             ss[zz]=i;
26         }
27         for(int j=1;j<=zz;j++)
28         {
29             if(ss[j]*i>mx)break;
30             fss[ss[j]*i]=1;
31             if(!(i%ss[j]))
32                 break;
33         }
34     }
35 }
36 long long ans=0x7ffffff;
37 int b[52],c[52],b2[52];
38 inline void dfs(int wz,long long sum){
39     //cout<<b[wz]<<endl;
40     long long an=0;
41     int d[52];
42      
43     for(int i=1;i<=n;i++)
44     {
45         an+=(a[i]%b[wz]);
46         a[i]/=b[wz];
47     }
48     if(sum+an>=ans)return;
49     memcpy(d,a,sizeof(a));
50     if(a[1]!=1&&a[1]!=0)
51     {
52         for(int i=1;i<=zz;i++)
53         {
54             if(b2[wz]*ss[i]>c[1])break;
55             b[wz+1]=ss[i];
56             b2[wz+1]=b2[wz]*ss[i];
57             dfs(wz+1,an+sum);
58             b[wz+1]=0;
59             b2[wz+1]=0;
60             memcpy(a,d,sizeof(a));
61         }
62     }
63     else
64     {
65         long long as=0;
66         for(int i=1;i<=n;i++)
67         {
68             if(a[i])as+=1;
69         }
70         int la=1;
71         for(int i=1;i<=wz;i++)
72         {
73             la*=b[i];
74         }
75         ans=min(ans,sum+an+as);
76     }
77 }
78 int main(){
79 //  freopen("coin.in","r",stdin);
80 //  freopen("coin.out","w",stdout);
81     scanf("%d",&n);
82     for(int i=1;i<=n;i++)
83     {
84         scanf("%d",&a[i]);
85         c[i]=a[i];
86     }
87     sort(a+1,a+n+1,bj);
88     sort(c+1,c+n+1,bj);
89     xs();
90     b[1]=1;b2[1]=1;
91     b[0]=1;b2[0]=1;
92     dfs(1,0);
93     printf("%lld\n",ans);
94     //while(1);
95     return 0;
96 }
View Code

 

 

 

posted @ 2017-09-03 17:39  Hzoi_joker  阅读(255)  评论(0编辑  收藏  举报