给定 m个食物,其中第 i个食物的种类为 ai。
请你设计一个食物套餐,对于该套餐:
- 唯一要求是设计好的套餐必须恰好包含 n个食物。
- 具体包含多少种食物,以及包含哪些种类的食物,不做要求,任你安排。
- 每种食物具体包含多少个,不做要求,任你安排。
我们的目标是通过合理安排套餐中包含的食物内容,从而使得利用给定食物,可以制作出的该套餐的数量越多越好。
输出能够制作出的套餐的最大可能数量。
输入格式
第一行包含两个整数 n,m。
第二行包含 m个整数 a1,a2,…,am。
输出格式
一个整数,表示能够制作出的套餐的最大可能数量。
如果根本不可能制作出任何套餐,则输出 0。
数据范围
前 4 个测试点满足 1≤m≤10。
所有测试点满足 1≤n≤100,1≤m≤100,1≤ai≤100。
输入样例1:
4 10 1 5 2 1 1 1 2 5 7 2
输出样例1:
2
输入样例2:
100 1 1
输出样例2:
0
输入样例3:
2 5 5 4 3 2 1
输出样例3:
1
输入样例4:
3 9 42 42 42 42 42 42 42 42 42
输出样例4:
3
解法:枚举答案or二分答案
枚举:
#include <bits/stdc++.h> using namespace std; int n, m; int a[105]; // 此题数据量不大 vector<pair<int, int>> b; // 种类,数量 int main() { // 输出能够制作出的套餐的最大可能数量 cin >> n >> m; int u; for (int i = 0; i < m; i++) { cin >> u; a[u]++; // 种类,数量 } if (n > m) { cout << 0; return 0; } if (n == m) { cout << 1; return 0; } for (int i = 0; i < 105; i++) { // 缩小范围 if (a[i] != 0) // 种类i的数量a[i]!=0 { b.push_back(make_pair(i, a[i])); } } // 枚举答案 int ans = m / n; // 最多有m/n个套餐 for (int i = ans; i >= 0; i--) { // 看每种食物是否可以提供给每份套餐几个,加起来看是否满足n int num = 0; // 最后与n比较 num:为每个套餐提供num个 for (vector<pair<int, int>>::iterator it = b.begin(); it != b.end(); it++) { num += (*it).second / i; } if (i == 0) { cout << 0; return 0; } else if (num >= n) { cout << i; return 0; } } }
二分:
#include <bits/stdc++.h> using namespace std; int n, m; int a[105]; // 此题数据量不大 vector<pair<int, int>> b; // 种类,数量 bool check(int t) // t为套餐个数 这里是对是否找到答案的判断 { int sum = 0; for (vector<pair<int, int>>::iterator it = b.begin(); it != b.end(); it++) { sum += (*it).second / t; } if (sum >= n) return true; else return false; } int main() { // 输出能够制作出的套餐的最大可能数量 cin >> n >> m; int u; for (int i = 0; i < m; i++) { cin >> u; a[u]++; // 种类,数量 } if (n > m) { cout << 0; return 0; } if (n == m) { cout << 1; return 0; } for (int i = 0; i < 105; i++) { // 缩小范围 if (a[i] != 0) // 种类i的数量a[i]!=0 { b.push_back(make_pair(i, a[i])); } } // 二分答案 int ans = m / n; // 最多有m/n个套餐 0~ans二分 int l = 0, r = ans; while (l < r) { int mid = (l + r + 1) / 2; if (check(mid)) { l = mid; } else r = mid - 1; } cout << l; }
二分模板:
while (l < r) { int mid = l + r >> 1; //(l+r)/2 if (check(mid)) r = mid; // check()判断mid是否满足性质 else l = mid + 1; }
尽量往左找目标
while (l < r) { int mid = l + r + 1 >> 1; //(l+r+1)/2 if (check(mid)) l = mid; else r = mid - 1; }
尽量往右找目标