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

题解:

  听说是个DP?! 

  为什么我只会搜索……(我还信(sha)誓(bi)旦(zhi)旦(zhang)的和hz各位大佬说这绝对不能DP……)

  显然每次都是选一个素数p,然后每个$a_{i}$可以表示成$a_{i}=k_{i}*p+rest_{i}$。那么$rest_{i}$是必须要用价值为1的硬币填,那么把$rest_{i}$减去,再给$a_{i}$除去$p$得到一个新数组,对于这个数组我们会发现它的处理和之前是一样,所以可以根据这个来dfs。

  然后就是剪枝。神奇的估值。因为我们知道每一次选$p$为倍数,$rest_{i}$是必须用所谓的价值为1的去填,那么我们可以统计这个$\sum_{i=1}^{n}rest_{i}$并与已知答案比较即可。

 #include<cstdio>
#include<cstring>
#include<algorithm>
inline int min(int a,int b){return a<b?a:b;}
using namespace std;
const int N=;
inline int read(){
int s=,k=;char ch=getchar();
while(ch<''||ch>'') k=ch=='-'?-:k,ch=getchar();
while(ch>&&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
}
int n;
int a[];
int ans=0x7fffffff;
int prim[];
bool vis[];
int k;
inline void init(){
for(int i=;i<=;i++){
if(!vis[i])
prim[++k]=i;
for(int j=;j<=k&&prim[j]*i<=;j++)
vis[i*prim[j]]=;
}
}
void dfs(int now,int sum,int tot){
int b[];
memcpy(b,a,sizeof(b));
for(int i=;i<=n;i++){
sum+=a[i]%now,a[i]/=now;
//if(a[i]==1) sum++,a[i]=0,from++;
}
// printf("now=%d sum=%d tot=%d a[n]=%d\n",now,sum,tot,a[n]);
if(a[n]){
int t=,z=;
int s=;
for(int q=;prim[q]<=a[n]+;q++) {
int i=prim[q];
z=;t=;
s=;
for(int j=;j<=n;j++){
if(a[j]<i) t++,z+=a[j];
s+=a[j]%i;
}
if(z+sum+n-t>=ans) break;
if(s+n-t+sum>=ans) continue;
dfs(i,sum,i*tot);
}
}
else{
for(int i=;i<=n;i++)
if(a[i]) sum++;
ans=min(ans,sum);
}
memcpy(a,b,sizeof(a));
}
int main(){ n=read();
init();
int need=;
for(int i=;i<=n;i++){ a[i]=read();
if(a[i]==){
i--,n--,need++;
}
}
if(n==){
printf("%d\n",need);
return ;
}
sort(a+,a++n); int t=,z=;
for(int q=;prim[q]<=a[n]+;q++){
int i=prim[q];
int sum=;
for(int j=;j<=n;j++){
sum+=a[j]%i;
if(a[j]<i&&j>t) t++,z+=a[j];
}
if(z+n-t>=ans) break;
if(sum+n-t>=ans) continue;
dfs(i,,i);//printf("sum[%d]=%d a[n]=%d\n",i,sum,a[n]);
}
printf("%d\n",ans+need);
}

话说自己至今才开搜索专栏……

【bzoj 3233】[Ahoi2013]找硬币 ——搜索的更多相关文章

  1. BZOJ 3233: [Ahoi2013]找硬币

    BZOJ 3233: [Ahoi2013]找硬币 标签(空格分隔): OI-BZOJ OI-DP Time Limit: 10 Sec Memory Limit: 64 MB Description ...

  2. BZOJ 3233: [Ahoi2013]找硬币( dp )

    dp(x)表示最大面值为x时需要的最少硬币数. 枚举x的质因数p,  dp(x) = min( dp(x/p) - (p-1) * sigma[a[i]/x] ). ----------------- ...

  3. [Bzoj3233][Ahoi2013]找硬币[基础DP]

    3233: [Ahoi2013]找硬币 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 924  Solved: 482[Submit][Status][ ...

  4. [AHOI2013]找硬币(搜索)

    [Ahoi2013]找硬币 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 348  Solved: 114[Submit][Status] Descri ...

  5. 【BZOJ 3233】 [Ahoi2013]找硬币

    [题目 描述] 小蛇是金融部部长. 最近她决定制造一系列新的货币. 假设她要制造的货币 的面值为 x1, x2, x3… 那么 x1 必须为 1, xb 必须为 xa 的正整数倍(b>a). 例 ...

  6. BZOJ3233:[AHOI2013]找硬币(DP)

    Description 小蛇是金融部部长.最近她决定制造一系列新的货币.假设她要制造的货币的面值为x1,x2,x3… 那么x1必须为1,xb必须为xa的正整数倍(b>a).例如 1,5,125, ...

  7. [bzoj3233] [Ahoi2013]找硬币

    一开始没什么思路...后来想到确定最大硬币面值就知道其他面值能取多少了..而且结果是可以由较小的面值转移过来的. f[i]表示最大面值为i时的最小硬币数.a[i]表示第i个物品的价钱. f[i]=mi ...

  8. [BZOJ 3233] 找硬币

    Link: BZOJ 3233 传送门 Solution: 在本蒟蒻看来算是一道比较神的$dp$了 一开始转移方程都没看出来…… 首先,如果确定了最大面值,是能推出其他面值的所有可能值的 从而发现最大 ...

  9. 【刷题】BZOJ 4566 [Haoi2016]找相同字符

    Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. Input 两行,两个字符串s1,s2,长度分别为 ...

随机推荐

  1. Course3-Python文件I/O

    1. 读取键盘输入 Python提供了两个内置函数从标准输入读入一行文本,默认的标准输入是键盘.如下: 1). raw_input. raw_input([prompt]) 函数从标准输入读取一个行, ...

  2. Jfinal调用Orcale存储过程

    因为项目需要,最近一直在学习Orcale存储过程,但发现在网上很少有人写Jave中Jfinal调用Orcale存储过程的文章,即使有也是几年前的,很多都不能用,今天给大家分享一段Jfinal调用Orc ...

  3. java死锁小例子

    package cn.com.io.threadDemo.ThreadSyn; /** * 通过两个属性值创建死锁 * 本程序通过两个线程各自锁定一个属性值,这样两个线程都无法结束,造成死锁 * @a ...

  4. jvm性能优化及内存分区

     jvm性能优化及内存分区 2012-09-17 15:51:37 分类: Java Some of the default values for Sun JVMs are listed below. ...

  5. .net开发微信(1)——微信订阅号的配置

    到微信公众平台按提示一直走下去后,可能遇到的难点就是填写Url和Token了. 开发文档里说,url是自己的服务器地址,Token随便写.但是一直提示Token验证失败. 解决办法:需要在服务器里新增 ...

  6. jsoup 使用总结2--高级用法之 :gt(n)

    jsoup 使用总结2--高级用法之 :gt(n) 大部分时候,我们使用jsoup解析网页的时候,都是直接找到某一类元素,或者按某种selector查询:具体使用方法可以参考jsoup官网文档 部分h ...

  7. polysh安装与使用-同时查看多台机器日志

    polysh简介 polysh 是一个交互式命令,可以在一台服务器上批量的对一批服务器进行处理,运行交互式命令.官方的简介如下: Polysh is a tool to aggregate sever ...

  8. js实现地图打印功能

    注意:js对地图的打印功能在arcgis10.1中才有提供,所以如果要使用esri自带的地图打印功能,必须使用arcgis 10.1或更高版本的地图打印模板.(由于官网和arcgis desktop提 ...

  9. 有终将被编程潮流淹没的程序员,那是因为没学python人工智能吧?

    2017年被称为中国人工智能元年--在两会时期,人工智能曾经成为国度计策,同时被写进当局报告.在从前的一年里,人工智能获得注重,已逐步浸透到别的行业,无人超市.主动驾驶.人脸识别.智能家居等" ...

  10. 解决0% [Waiting for headers] 导致的unable to lock the administration directory (/var/lib/dpkg/) is another process using it

    这是我在配置vim的YouCompleteMe时遇到的问题,我需要使用CMake来编译YCM. 在我输入 $ sudo apt install cmake 由于网络原因导致安装一直卡在0% [Wait ...