ZROI117 【17 普及 23】知足

尽管这些题目都是五月天的经典歌曲,但和五月天毫无关系(好歹说一句:小明正在听五月天的歌《知足》,突然心情很差,想出了一道机智的题,希望机(yu)智(chun)的你去切(bu cun zai de)了他。
你现在正在设计一套新的货币系统。这套货币系统有以下要求:
  1. 一共有 K种面值的纸币(没有硬币等其他货币)。
  2. 最小的纸币面值为 1 元。
  3. 每种纸币的面值为前一种纸币面值的 2345 倍。
现在你希望设计这样一套货币系统,使得凑出 n 元所需的纸币数量尽量少(注意这里不设找零,即你只能拿若干张纸币加起来凑出 n 元)。你可以假设每种面值的纸币都有任意多张。

输入格式

输入一行两个正整数 nK,以一个空格隔开。

输出格式

输出一个正整数,表示凑出 n 元至少需要的纸币数量。

样例输入

1025 6

样例输出

2

样例说明

纸币面值:1, 4, 16, 64, 256, 1024

数据规模和约定

子任务1(20分):n10^18,K10 子任务2(80分):n10^18,K100

题解

感觉智商越来越低了,,动态开点线段树被做成单调队列,nuo,普及组的题都只能敲暴力,orz orz 20分做法,爆搜。 满分做法:dp[n,k]表示,还可以新有K种货币,将这k+1种货币构成n元钱的最小纸币张数,并且第K+1的面额为1。 有个很显然的贪心我们也在上述20分爆搜写的时候发现,在一组货币后,我们一定是优先选金额大的再选金额小的。而这里,我们枚举一下一张货币的面额(从2-->5)d,那么一定是后面的货币分配了n-n%d元,这样才更优。由于那n%d太小,只有面额1能选便分配。 这样之后看似我们与之前定的面额矛盾,因为现在变成了K+1面额为d了。但实际上我们如果将(n-n%d)和面额d同时除上一个d,那么我们就又转化为之前的dp状态了。 那么就有 dp[n,k] = for ( d 2-->5) min(dp[n,k],dp[(n-n%d)/d,k-1]+n%d) 这里面有很多冗余状态,且显然数组存不下。我们开个hash表或者map都是可以的。 code:
#include<iostream>
#include<map>
#include<cstdio>
#include<algorithm>
using namespace std;
map<long long,long long>dp[105];
long long n,k;
long long dfs(long long n,long long k)
{
	if(dp[k][n]) return dp[k][n];
	if(k==1) return n;
	if(!n) return 0;
	long long bbest = 1e18;
	for(int i=2;i<=5;i++)
	{
		bbest = min(bbest,dfs(n/i,k-1)+n%i);
	}
	return dp[k][n] = bbest;
}
int main()
{
	scanf("%lld%lld",&n,&k);
	printf("%lld",dfs(n,k));
}
 
posted @ 2018-08-10 23:46  Newuser233  阅读(8)  评论(0)    收藏  举报