@AkamemakA
2022-06-29T04:57:51.000000Z
字数 1219
阅读 130
Atcoder
题解
题目链接:点我
一个人有元钱,他的面前有9个数字,每个数字对应的价格为。这个人有一个数,开始时为。如果这个人购买了第个数字,那么他的对应的减去,他的对应的会变为。(一个数可以被购买无数次。)
求如何分配他的N元钱,是的他获得的值最大。输出这个最大值。
5
5 4 3 3 2 5 3 5 3
95
可以购买第个和第个数字。这样花费是,得到的数是。
可以证明,找不到更大的方案可以使答案大于。
20
1 1 1 1 1 1 1 1 1
99999999999999999999
可以购买次第个数。这样会得到一个最大的位数。
注意:答案可能不适用于64位整型数。
这道题是一道妥妥的贪心。
要使得所得的数最大,那么首先决定性的因素便是这个数的位数。所以,我们可以找到数组中的最小值,便可以得到答案的位数。
决定了答案的位数后,我们从1到枚举,对于每一位,我们从后往前枚举(因为要使答案最大化,则应尽量选靠后的数字)题中给出的个数字,从中找到第一个符合剩余钱数条件的数。
要注意的是,不是只要找的一个数,使得剩余的即可。若后面的数不足以凑出足够的位数,那么这个数就无法达到应有的位数。因此,在考虑一个数时,应该考虑给后面留下足够多的钱,即:
if(c*(len-i)+a[j]<=n)
//c为C数组中最小的数,len-i为剩余的位数,j为枚举的9个数,n为剩余的钱数。
另外,目标数可能不适用于64位整型数,因此答案要用类型存储。
完美解决。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n;
int a[10],c=0x3f3f3f3f; //c为C数组中最小的数
int main()
{
cin>>n;
for(int i=1;i<=9;i++){
scanf("%d",&a[i]);
c=min(c,a[i]); //找到最小数
}
int len=n/c; //len为答案的位数
string ans=""; //string储存答案
for(int i=1;i<=len;i++) //枚举位数
for(int j=9;j>=1;j--) //枚举数字
if((long long)(c*(len-i))+a[j]<=n){ //注意两个数相乘可能会爆int,因此强转成long long
ans+=(j+'0'); //ans=ans*10+j
n-=a[j]; //n为剩余的钱数
break;
}
cout<<ans;
return 0;
}
完结撒花~