BZOJ3233:[AHOI2013]找硬币(DP)

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

Solution

因为选的序列是倍数的原因,所以我们可以得到一个贪心:尽可能选大的。

也就是我们从大到小确定面额,如果当前确定的面额为$x$,那么所有兔子剩下需要付的就是$a[i]\% x$。

设$f[i]$表示当前最小面值为$i$时的最少付钱次数。

初始化$f[i]=\sum_{j=1}^na[j]/i$。

设$p$为$f[i]$的一个质因数

转移$f[i/p]=min(f[i/p],f[i]+\sum_{j=1}^{n} a[j]\% i/(i/p))$

并且你需要一个线筛来快速找出一个数的所有质因数。

为什么这么转移懒得写了,反正就是基于贪心的思想应该并不难理解QAQ

我:为啥这个初始化不上取整啊……难不成钱不够兔子还给你抹个零……
$sugar$:你别说还真的抹个零,因为零头在后面$DP$会付掉的……

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define N (100009)
 5 using namespace std;
 6 
 7 int n,cnt,maxn,a[N],prime[N],d[N],f[N];
 8 
 9 void Euler()
10 {
11     for (int i=2; i<=maxn; ++i)
12     {
13         if (!d[i]) {prime[++cnt]=i; d[i]=i;}
14         for (int j=1; j<=cnt && i*prime[j]<=maxn; ++j)
15         {
16             d[i*prime[j]]=prime[j];
17             if (i%prime[j]==0) break;
18         }
19     }
20 }
21 
22 int main()
23 {
24     scanf("%d",&n);
25     for (int i=1; i<=n; ++i)
26         scanf("%d",&a[i]), maxn=max(maxn,a[i]);
27     Euler();
28     memset(f,0x7f,sizeof(f));
29     for (int i=maxn; i>=1; --i)
30     {
31         int sum=0;
32         for (int j=1; j<=n; ++j)
33             sum+=a[j]/i;
34         f[i]=min(f[i],sum);
35         int x=i;
36         while (x>1)
37         {
38             int p=d[x],sig=0;
39             for (int j=1; j<=n; ++j)
40                 sig+=a[j]%i/(i/p);
41             f[i/p]=min(f[i/p],f[i]+sig);
42             while (x%p==0) x/=p;
43         }
44     }
45     printf("%d\n",f[1]);
46 }
posted @ 2019-01-04 18:46  Refun  阅读(210)  评论(0编辑  收藏  举报