题目描述
JM的太爷爷的太爷爷的太爷爷……的太爷爷喜欢攒零钱,并把攒零钱作为祖训传承至今,现在已经攒了整整一箱子的硬币,JM清点了一下发现箱子里一共有(n)枚硬币。众所周知,古代的钱币放到现在都很值钱,所以这些硬币的价值并不相同。不过,由于寒域爷施了石志魔法,这些硬币的价值都是(2)的幂次。也就是说,对于任意的第(i)枚硬币,其价值(a_i)一定满足(a_i=2^d),其中(d)是某个非负整数。
现在,石乐志的JM想拿这些硬币去买菜,他有(q)种想买的菜。因为石乐志,JM认为硬币的价值并不重要,而硬币的数量是最重要的。所以在买菜之前,他想事先知道,对于每种价格为(b_j)的菜,他最少需要用掉多少枚硬币才能将其买下。另外,由于JM有强迫症,他不希望他在买菜的时候还需要找零。
他希望你帮他分别计算买这(q)种菜的所需硬币数。注意,是分别计算,每种菜的求解之间是互相独立的。
输入格式
第一行两个正整数(n)和(q),表示JM的硬币数和JM想买的菜的种类数。
接下来一行(n)个正整数(a_i),表示每个硬币的价值。输入保证(a_i=2^d),其中(d)是某个非负整数。
接下来(q)行,每行一个正整数(b_j),表示每种菜的价格。
输出格式
输出(q)行,每行一个正整数,表示买下每种菜所需的最少硬币个数。如果无论如何也无法凑齐价格(注意不能找零),则输出(-1)。
数据范围
(1leq n,q leq 2*10^5)
(1leq a_i,b_j leq 2*10^9)
思路
存储:我们可以令(a[i])表示面值为(2^i)的硬币有多少枚。
这是一道贪心题,对于每一个(x),我们从2的高次幂往低次扫,能取就尽量取完。比如现在硬币面额为(2^i),所取的数量(t)应为满足(tleq a[i])且(t*2^ileq x) 的最大值。
如果这样取最终能使x归零,那么有解,且最优取法如上;否则无解。
为什么呢?因为低次幂可以拼成高次幂,而高次幂无法拆成低次幂。所以我们优先把高次幂取掉,既减少了所用硬币数量,又留下更多灵活的小面额给接下来的步骤。(感性理解一下)
注意:题目所给的数据范围很接近int的最大值,小心溢出。
代码
#include<cstdlib>
#include<algorithm>
using namespace std;
int a[30];
int main(){
int i,j,n,m,x,ans;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
int t=-1;
scanf("%d",&x);
while(x){
x>>=1;
t++;
}
a[t]++;
}
for(i=1;i<=m;i++){
scanf("%d",&x);
ans=0;
for(j=0;(1ll<<j+1)<=x;j++){
}
while(x&&j>=0){
int t=min(a[j],x/(1<<j));
x-=t*(1ll<<j);
ans+=t;
j--;
}
if(!x) printf("%d
",ans);
else printf("-1
");
}
return 0;
}