BZOJ1816 CQOI2010 扑克牌 贪心

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1816

题意:有$N$堆牌,第$i$堆牌有$c_i$张牌,还有$M$张$joker$,每一次可以从$N$堆牌中任选一张组成一副牌,或者在任意$N - 1$堆中选择$1$张牌加上一张$joker$组成一副牌,问最多能组成多少副牌。$N \leq 50 , m , c_i \leq 5 \times 10^8$


清流题qwq

每一次的消除一定是在牌最少的一堆使用$joker$,$joker$就等效于这一堆中额外的一张牌。所以先考虑加完$joker$一起减的情况,也就是先把第一少的堆加$joker$直至与第二少的堆牌量相同,然后在前两少的堆中同时加$joker$直至前三堆牌量相同,这么一直做下去,直到$joker$不够或者$N$堆加成一样高,把剩下的$joker$平摊在每一堆上就是最优策略。

然而这样子会有一个问题:一次取牌只能取出一张$joker$,但我们的方案中很有可能一次取出多张$joker$。我们不妨这样考虑:在排序之后,前两堆牌每一次至少会取出一张牌,前三堆牌每一次至少会取出两张牌,以此类推,我们可以得到一个取牌的上界,将这个上界与上面的答案取$min$即可

所以请无视我的高精$QuQ$

 #include<bits/stdc++.h>
 #define ll long long
 using namespace std;

 const int MOD = 1e9;
 inline ll read(){
     ll a = ;
     char c = getchar();
     while(!isdigit(c))
         c = getchar();
     while(isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return a;
 }

 struct Bignum{
     ];
     Bignum(ll x){
         ;
         ){
             num[i++] = x % MOD;
             x /= MOD;
         }
     }
     Bignum operator +=(ll x){
         ;
         while(x){
             num[i] += x % MOD;
             if(num[i] > MOD){
                 num[i + ]++;
                 num[i] -= MOD;
             }
             x /= MOD;
             i++;
         }
         return *this;
     }

     ll operator /(int x){
         ll sum =  , ans = ;
          ; i >=  ; i--){
             sum = sum * MOD + num[i];
             ans = ans * MOD + sum / x;
             sum %= x;
         }
         return ans;
     }
 };
 ll num[];

 int main(){
     freopen("easy.in" , "r" , stdin);
     freopen("easy.out" , "w" , stdout);
     int N;
     ll M;
     N = read();
     M = read();
      ; i <= N ; i++)
         num[i] = read();
     sort(num +  , num + N + );
     ;
     ll minN = 1e18 + ;
     Bignum sum = num[dir];
     ] - num[dir] <= M / dir){
         M -= (num[dir + ] - num[dir]) * dir;
         sum += num[dir + ];
         minN = min(minN , sum / dir);
         dir++;
     }
     cout << min(minN , num[dir] + M / dir) << endl;
     ;
 }
上一篇:mysql简单操作


下一篇:(转)Awsome Domain-Adaptation