[BZOJ 3233] 找硬币
Link:
Solution:
在本蒟蒻看来算是一道比较神的$dp$了
一开始转移方程都没看出来……
首先,如果确定了最大面值,是能推出其他面值的所有可能值的
从而发现最大面值能由较小的面值转移过来:
$dp[i]=min\{ dp[i/j]-sum\{ a[k]/i*(j-1)\} \}$
(其中$a[k]/i$是大面值需要的个数,$a[k]/(i/j)$是小面值需要的个数,余数不处理)
下面就要处理$j$的取值了,
首先要看到一个比较明显的性质:用$dp[i]$转移肯定不会比用$dp[i/j]$差,毕竟种类更多
于是$j$应为质数($i$的质因数),否则$i/j<i/MinPrime$,从而$dp[i/MinPrime]$一定不比$dp[i/j]$差
因此不取合数对答案没有影响
在线性筛时可以顺便求出$x$的最小质因数$mn[x]$,方便后面求出$x$的每一个质因数
Code:
#include <bits/stdc++.h> using namespace std;
const int MAXN=1e5+;
int n,tot,mx,cnt,t,mn[MAXN],dat[MAXN],pri[MAXN],vis[MAXN],dp[MAXN],res; int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&dat[i]),mx=max(mx,dat[i]),tot+=dat[i]; mn[]=;
for(int i=;i<=mx;i++) //线性筛
{
if(!vis[i]) pri[++cnt]=i,mn[i]=i;
for(int j=;j<=cnt && i*pri[j]<=mx;j++)
{
vis[i*pri[j]]=;mn[i*pri[j]]=pri[j];
if(i%pri[j]==) break;
}
} for(int i=;i<=mx;i++) dp[i]=tot;res=tot;
for(int i=;i<=mx;res=min(res,dp[i]),i++)
for(int j=i;j>;dp[i]=min(dp[i],t))
{
t=dp[i/mn[j]];
for(int k=;k<=n;k++) t-=dat[k]/i*(mn[j]-);
while(mn[j]==mn[j/mn[j]]) j/=mn[j];
j/=mn[j];
}
printf("%d",res);
return ;
}
Review:
1、关于质因数分解的优化
只能算是常数上的优化吧
由于筛法时我们要保证合数只被自己的最小质因数筛去,
于是我们顺便记录下每个数最小的质因数$mn[x]$,再一步步推出下一个质因数
推导的方式
while(mn[j]==mn[j/mn[j]]) j/=mn[j];
j/=mn[j];
2、$dp$的思考技巧
如果不清楚对什么量$dp$,可以查找那些量可以推出上一步/下一步的值,往往对这些量$dp$
[BZOJ 3233] 找硬币的更多相关文章
- BZOJ 3233: [Ahoi2013]找硬币
BZOJ 3233: [Ahoi2013]找硬币 标签(空格分隔): OI-BZOJ OI-DP Time Limit: 10 Sec Memory Limit: 64 MB Description ...
- BZOJ 3233: [Ahoi2013]找硬币( dp )
dp(x)表示最大面值为x时需要的最少硬币数. 枚举x的质因数p, dp(x) = min( dp(x/p) - (p-1) * sigma[a[i]/x] ). ----------------- ...
- [Bzoj3233][Ahoi2013]找硬币[基础DP]
3233: [Ahoi2013]找硬币 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 924 Solved: 482[Submit][Status][ ...
- [AHOI2013]找硬币(搜索)
[Ahoi2013]找硬币 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 348 Solved: 114[Submit][Status] Descri ...
- [BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash)
[BZOJ 4820] [SDOI2017] 硬币游戏(高斯消元+概率论+字符串hash) 题面 扔很多次硬币后,用H表示正面朝上,用T表示反面朝上,会得到一个硬币序列.比如HTT表示第一次正面朝上, ...
- 【bzoj 3233】[Ahoi2013]找硬币 ——搜索
Description 小蛇是金融部部长.最近她决定制造一系列新的货币.假设她要制造的货币的面值为x1,x2,x3… 那么x1必须为1,xb必须为xa的正整数倍(b>a).例如 1,5,125, ...
- 【BZOJ 3233】 [Ahoi2013]找硬币
[题目 描述] 小蛇是金融部部长. 最近她决定制造一系列新的货币. 假设她要制造的货币 的面值为 x1, x2, x3… 那么 x1 必须为 1, xb 必须为 xa 的正整数倍(b>a). 例 ...
- 【bzoj3233】【ahoi2013】找硬币
题意: 求确定n种货币面额x1..xn满足 x1=1 且xi为xj的整数倍(i>j) 给定n个物品价格ai 求使用上面货币最少需要硬币数(不能找零) 题解: 动态规划 听说网上的题解都是搜索的做 ...
- [BZOJ 1042] [HAOI2008] 硬币购物 【DP + 容斥】
题目链接:BZOJ - 1042 题目分析 首先 Orz Hzwer ,代码题解都是看的他的 blog. 这道题首先使用DP预处理,先求出,在不考虑每种硬币个数的限制的情况下,每个钱数有多少种拼凑方案 ...
随机推荐
- wait for it
- taotao购物车
功能分析: 1.在用户不登陆的情况下也可以使用购物车,那么就需要把购物车信息放入cookie中. 2.可以把商品信息,存放到pojo中,然后序列化成json存入cookie中. 3.取商品信息可以从c ...
- 安卓titlebar的组合控件使用
http://blog.csdn.net/itachi85/article/details/51435187
- bzoj 5099 [POI2018]Pionek 计算几何 极角排序
[POI2018]Pionek Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 269 Solved: 80[Submit][Status][Disc ...
- c++(类)构造函数、复制构造函数
复制构造函数是一种特殊的构造函数,它的作用是用一个已经存在的对象去初始化另一个对象.一般情况下不需要自行定义复制构造函数,系统默认提供一个逐个复制成员值的复制构造函数. 何时要使用呢? 1.将新对象初 ...
- (转)用python实现抓取网页、模拟登陆
涉及一系列内容,部分已在前面转载,仍转自crifan: http://www.crifan.com/how_to_use_some_language_python_csharp_to_implemen ...
- Nginx的client_header_buffer_size和large_client_header_buffers学习
之前看到有人写的一篇关于nginx配置中large_client_header_buffers的问题排查的文章,其中提到: large_client_header_buffers 虽然也可以在serv ...
- jsp和servlet之间传数据
一.jsp与java文件传递数据可以使用Servlet类来传递,jsp将数据存入到request对象中,Servlet类获取这个request对象,并将数据取出. 示例代码如下: JSP代码: < ...
- 使用FindBugs-IDEA插件找到代码中潜在的问题
另一篇使用文档,参照:https://www.cnblogs.com/huaxingtianxia/p/6703315.html 我们通常都会在APP上线之后,发现各种错误,尤其是空指针异常,这些错误 ...
- 基于多线程的TCP socket通信经典案例
服务器端 package com.thinkvenus.study.socket; import java.io.BufferedReader; import java.io.IOException; ...