Codeforces725E Too Much Money【枚举】

分析:容易注意到答案只可能是加一个金币。因为加两个可以规约为加一个。

所以可以枚举加的金币为i,然后依照题意模拟扣金币的过程。每次找到一个当前能扣的最大的金币,一次性把这种金币扣完。这样每种金币只被找到一次,由$1+2+...+n=n(n+1)/2$可以推得最多找到$\sqrt n$种金币。预处理当前最大能找的金币为$x$时找到的金币,可以做到$O(c\sqrt c)$

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 202000;
 5 
 6 int c,n;
 7 int a[maxn];
 8 int cnt[maxn];
 9 int pre[maxn];
10 
11 int check(int coin,int now){
12     int lastget = coin;
13     while(coin){
14     int dt = 0;
15     if(lastget >= now) dt = max(now,pre[lastget]);
16     else dt = pre[lastget];
17     if(dt == 0) break;
18     if(coin - 1ll*cnt[dt]*dt <= 0){
19         coin %= dt;
20     }else{
21         coin -= cnt[dt]*dt;
22     }
23     lastget = min(coin,dt-1);
24     }
25     if(coin == 0) return 0;
26     else return 1;
27 }
28 
29 int main(){
30     scanf("%d%d",&c,&n);
31     for(int i=1;i<=n;i++){
32     scanf("%d",&a[i]);
33     cnt[a[i]]++;
34     pre[a[i]] = a[i];
35     }
36     for(int i=1;i<=c;i++){
37     if(!pre[i]) pre[i] = pre[i-1];
38     }
39     for(int i=1;i<=c;i++){
40     cnt[i]++;
41     if(check(c,i)){
42         printf("%d\n",i);
43         return 0;
44     }
45     cnt[i]--;
46     }
47     puts("Greed is good");
48     return 0;
49 }
View Code

 

posted @ 2022-07-25 22:12  menhera  阅读(28)  评论(0编辑  收藏  举报