给定 m 个食物,其中第 i 个食物的种类为 ai。
题目:
请你设计一个食物套餐,对于该套餐:
- 唯一要求是设计好的套餐必须恰好包含 n
- 个食物。
- 具体包含多少种食物,以及包含哪些种类的食物,不做要求,任你安排。
- 每种食物具体包含多少个,不做要求,任你安排。
我们的目标是通过合理安排套餐中包含的食物内容,从而使得利用给定食物,可以制作出的该套餐的数量越多越好。
输出能够制作出的套餐的最大可能数量。
这个题目就是使用二分找到最大套餐数;
对于每种事物,我们可以记录每种事物的数量,使用b[i]代表套餐中每种事物的数量;
a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8]......;
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 ; }