C题

题目链接Problem - C - Codeforces

题目描述

思路🤖

  • 对于这道题,首先我们能想到最小的组数肯定是数量最多的那个卡片的数量(mx),因为这个值的每一个卡片不能在同一个组里面。
  • 我们首先需要考虑是否能够保住这个sum/mx这个答案,甚至可以用k来增加答案的值。
  • 而要保住这个答案,要不就是刚好sum%mx==0,即刚好没加k前大小就是sum/mx,然后因为有mx组,所以卡组大小又多了k/mx,
  • 另一种可能就是k和多出的牌数再凑一层(指的是让sum%mx==0,用k来增大sum)出来,判断需要补的牌数和k的大小差即可。
  • 如果两者都不可以,那就需要减少卡组大小,看剩余的牌数可否成为新的组。
  • 如果减少一次卡组大小也不可以,就需要把卡组大小再减小,减小了卡组大小,剩余的数量就多了mx,再判断是否可以成为新的组,一直循环直到可以即输出。

时间复杂度:O(n)

代码💯

#include <bits/stdc++.h>
#define int long long 
using namespace std;
const int N=2e5+10;
int n,k;
int a[N];
void solve()
{
         cin>>n>>k;
        int mx=0,sum=0;
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
            sum+=a[i];
            mx=max(mx,a[i]);
        }
        int mans=sum/mx;
        //如果刚好就直接k来增添答案即可
       if (sum % mx == 0) {
		cout << min(mans + k / mx,n) << endl; 
        return;
	  }
      //如果不够就看k能不能和多出来的再组一行
	 if (k >= (mx - sum % mx)) {
		k -= (mx - sum % mx);
        mans++;
		cout << min(mans + k / mx,n) << endl; 
        return;
	}
	//此时k的作用不是继续增加mans,而是尽可能保住mans
	//k补不上空缺,我们先尝试增加mx,再不行就减层
	int res = sum % mx;//res标记的是指多出来的数
	while (1) {
		if (res % mans == 0) {//如果能够刚好保住
			cout << mans << endl; 
            return;
		}
		if (k >= (mans - res % mans)) {//如果能用k来保住
			cout << mans << endl; 
            return;
		}
		mans--; 
        res += mx;//少了一层多出来的就多mx
	}
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        solve();
    }
    return 0;
}

警示

  • 由于数据范围较大,所以我们需要用到long long,不然会爆数据
  • 因为只有n个数,所以肯定答案肯定小于等于n,所以在第一种情况要和n取最小值。

 

 posted on 2024-09-28 20:00  熙玺  阅读(30)  评论(0编辑  收藏  举报

Shu-How Zの小窝

Loading...