给定 m 个食物,其中第 i 个食物的种类为 ai
题目:

请你设计一个食物套餐,对于该套餐:

  • 唯一要求是设计好的套餐必须恰好包含 n
  • 个食物。
  • 具体包含多少种食物,以及包含哪些种类的食物,不做要求,任你安排
  • 每种食物具体包含多少个,不做要求,任你安排

我们的目标是通过合理安排套餐中包含的食物内容,从而使得利用给定食物,可以制作出的该套餐的数量越多越好。

输出能够制作出的套餐的最大可能数量。


这个题目就是使用二分找到最大套餐数;
对于每种事物,我们可以记录每种事物的数量,使用b[i]代表套餐中每种事物的数量;
a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8]......;
b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8]......;
设t为该套餐的数量,则t * b[1] <= a[1] , t * b[2] <= a[2]......以此类推;
我们可以得到 t*(b[1] + b[2] + b[3] + ....) <= a[1] + a[2] + a[3] + ......;
b[1] + b[2] + b[3] + .... = n;
所以t <= (a[1] + a[2] + a[3] + ......) / n;
故二分t即可得到答案
#include<bits/stdc++.h>
#define int long long
typedef long long ll;
using namespace std;
const int N = 1e3 + 10;
const int mod  = 1e9 + 7;
int n,m;
vector<int> a(N,0);
map<int,int> mp;    //统计每种食物的数量
bool check(int mid){    //二分判断
    if(mid == 0) return 1;  //为0肯定满足,返回1
    int sum = 0;
    for (auto i : mp) {
        sum += i.second/mid ;   //计算 sum之和是否大于等于 n
    }
    return sum >= n;    //大于等于n就意味着 结果在mid或mid右边
}
void solve(){
    cin>>n>>m;
    for(int i = 1;i <= m;i++){
        cin>>a[i];
        mp[a[i]]++;
    }
    if(m < n){
        cout<<"0"<<endl;    //为0直接特判
        return;
    }
    int l = 0,r = 100;
    while (l < r){  //相当于找右边界
        int mid  = (l + r + 1) >> 1;    //有加必有减
        if(check(mid)) l = mid;
        else r = mid - 1;   //减
    }
    cout<<r<<endl;//输出l或r均可
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    int t = 1;
    //cin>>t;
    while(t--){
        solve();
    }
    return 0 ;
}