给定 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 ;
}

京公网安备 11010502036488号