• XJTUOJ #1023 JM的祖传零钱箱


    题目描述

    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;
    }
  • 相关阅读:
    Flink--Window apply
    Flink--time-window 的高级用法
    Flink的Windows
    Flink的流处理--KeyBy
    Flink的分布式缓存
    Flink的广播变量
    Flink--本地执行和集群执行
    Flink-- 数据输出Data Sinks
    存储管理-页式管理
    存储管理-覆盖技术和交换技术
  • 原文地址:https://www.cnblogs.com/landmine-sweeper/p/13809369.html
Copyright © 2020-2023  润新知