[关闭]
@AkamemakA 2022-06-29T04:57:51.000000Z 字数 1219 阅读 130

Atcoder 题解

Atcoder Beginner Contest 257 problem E 题解


题目链接:点我

题目大意

一个人有元钱,他的面前有9个数字,每个数字对应的价格为。这个人有一个数,开始时。如果这个人购买了第个数字,那么他的对应的减去,他的对应的会变为。(一个数可以被购买无数次。)

求如何分配他的N元钱,是的他获得的值最大。输出这个最大值。

样例输入1

  1. 5
  2. 5 4 3 3 2 5 3 5 3

样例输出1

  1. 95

样例解释1

可以购买第个和第个数字。这样花费是,得到的数是
可以证明,找不到更大的方案可以使答案大于

样例输入2

  1. 20
  2. 1 1 1 1 1 1 1 1 1

样例输出2

  1. 99999999999999999999

样例解释2

可以购买次第个数。这样会得到一个最大的位数。
注意:答案可能不适用于64位整型数。

数据范围


解析

这道题是一道妥妥的贪心

要使得所得的数最大,那么首先决定性的因素便是这个数的位数。所以,我们可以找到数组中的最小值,便可以得到答案的位数

决定了答案的位数后,我们从1到枚举,对于每一位,我们从后往前枚举(因为要使答案最大化,则应尽量选靠后的数字)题中给出的个数字,从中找到第一个符合剩余钱数条件的数。

要注意的是,不是只要找的一个数,使得剩余的即可。若后面的数不足以凑出足够的位数,那么这个数就无法达到应有的位数。因此,在考虑一个数时,应该考虑给后面留下足够多的钱,即:

  1. if(c*(len-i)+a[j]<=n)
  2. //c为C数组中最小的数,len-i为剩余的位数,j为枚举的9个数,n为剩余的钱数。

另外,目标数可能不适用于64位整型数,因此答案要用类型存储。

完美解决。


代码实现

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=1e6+5;
  4. int n;
  5. int a[10],c=0x3f3f3f3f; //c为C数组中最小的数
  6. int main()
  7. {
  8. cin>>n;
  9. for(int i=1;i<=9;i++){
  10. scanf("%d",&a[i]);
  11. c=min(c,a[i]); //找到最小数
  12. }
  13. int len=n/c; //len为答案的位数
  14. string ans=""; //string储存答案
  15. for(int i=1;i<=len;i++) //枚举位数
  16. for(int j=9;j>=1;j--) //枚举数字
  17. if((long long)(c*(len-i))+a[j]<=n){ //注意两个数相乘可能会爆int,因此强转成long long
  18. ans+=(j+'0'); //ans=ans*10+j
  19. n-=a[j]; //n为剩余的钱数
  20. break;
  21. }
  22. cout<<ans;
  23. return 0;
  24. }

完结撒花~

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注