bzoj3233
来源:互联网 发布:金融入门书 知乎 编辑:程序博客网 时间:2024/06/11 08:56
题意:
小蛇是金融部部长。最近她决定制造一系列新的货币。假设她要制造的货币的面值为x1,x2,x3… 那么x1必须为1,xb必须为xa的正整数倍(b>a)。例如 1,5,125,250就是一组合法的硬币序列,而1,5,100,125就不是。不知从哪一天开始,可爱的蛇爱上了一种萌物——兔纸!从此,小蛇便走上了遇上兔纸娃娃就买的不归路。某天,小蛇看到了N只可爱的兔纸,假设这N 只兔纸的价钱分别是a1,a2…aN。现在小蛇想知道,在哪一组合法的硬币序列下,买这N只兔纸所需要的硬币数最少。买兔纸时不能找零。
#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>#include<iostream>#define N 60#define M 110000using namespace std;int f[M],a[N],n,ans,lim,p[M],pl;bool b[M];void get_p(){ for(int i=2;i<M;i++) { if(b[i]==0) p[++pl]=i; for(int j=1;j<=pl;j++) { if(i*p[j]>=M) break; b[i*p[j]]=1; if(i%p[j]==0) break; } }}int main(){ get_p(); scanf("%d",&n); lim=n*20; int mx=0; for(int i=1;i<=n;i++) {scanf("%d",&a[i]);mx=max(mx,a[i]);} memset(f,63,sizeof(f)); f[1]=0; for(int i=1;i<=mx;i++) { if(f[i]>lim) continue; for(int j=1;i*p[j]<=mx;j++) { int t=0; for(int k=1;k<=n;k++) t+=(a[k]/i)%p[j]; f[i*p[j]]=min(f[i*p[j]],f[i]+t); } } ans=lim; for(int i=1;i<=mx;i++) { if(f[i]>lim) continue; int t=f[i]; for(int j=1;j<=n;j++) t+=a[j]/i; ans=min(ans,t); } printf("%d\n",ans); return 0;}
题解: 看到动态规划的tag才幡然醒悟
因为都是倍数关系,所以可以贪心。
考虑这样算答案:
先把所有xi(i>1)变为
将所有数模x1累加进答案,然后每个数除x1。再将所有数模x2累加进答案,然后每个数除x2。。。一直做到最后一个x
正确性显然。
然后就可以对这个东西dp了。
f[i]表示前面除的数的积为i所累加的数最小是多少,枚举i的倍数转移。
复杂度很稳,不知道为什么会T。。
注意答案上界是nlogn,减一下枝就能过了。。
网上还有一个剪枝是枚举质数倍转移,好像这个剪枝比较强。。
0 0
- bzoj3233
- bzoj3233 [Ahoi2013]找硬币
- bzoj3233 找硬币 动态规划&线性筛
- BZOJ3233 [Ahoi2013]找硬币(线性筛+dp)
- Python 操作MySQL中文显示乱码的解决方法
- idea的使用,想到哪里就写到哪里
- 常用正则表达式
- 欢迎使用CSDN-markdown编辑器
- 基于Raspbian(树莓派)搭建web安全练习环境(二)
- bzoj3233
- JS中的数组转变成JSON格式字符串的方法
- Githup命令行
- Spinner的使用
- Qt学习
- 1074. Reversing Linked List 解析
- 杭电1016Prime Ring Problem DFS 搜索
- PAT1054 求平均值
- 关于股权激励方案建议参考