注意: \color{red}{注意:} 注意: 个人博客传送门
A. 平均成绩
思路:
- 按照题目意思计算即可
时间复杂度: O ( 1 ) O(1) O(1)
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
double a, b, c;
std::cin >> a >> b >> c;
std::cout << ((a + b + c) / 3 > 60 ? "YES\n" : "NO\n");
return 0;
}
B. 套餐设计
题目大意:
- 让我们找到最大的套餐数量,要保证每个套餐的物品是一模一样的,求最大数量
思路:
- 二分这个最大数量,只要找到一个 Σ i = 1 100 a i x \Sigma^{100}_{i=1} \frac{a_i}{x} Σi=1100xai 最大即可
- 所以这个 x x x 可以满足单调性,我们可以设 l = 0 , r = m / n l = 0, r = m / n l=0,r=m/n ,这样二分即可
时间复杂度: O ( l o g n ) O(logn) O(logn)
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
std::vector<int> a(105);
for (int i = 0; i < m; i++) {
int x;
std::cin >> x;
a[x]++;
}
int l = 0, r = m / n;
while (l < r) {
int mid = l + r + 1 >> 1;
auto check = [&](int mid) {
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum += a[i] / mid;
}
return sum >= n;
};
if (check(mid)) {
l = mid;
} else {
r = mid - 1;
}
}
std::cout << l << "\n";
return 0;
}
C. 分班
思路:
- 首先,我们要保证最小值与最大值的相差不能超过
l
,然后如果满足这个条件的数的个数小于n
,就一定不可能 - 然后,我们要满足每隔
k
个位置选一个数,这样才能保证最小值,等选完一轮后,如果个数小于n
,那么我们就从后往前选,保证总和尽可能大
时间复杂度: O ( n ) O(n) O(n)
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, k, l;
std::cin >> n >> k >> l;
std::vector<int> a(n * k);
for (int i = 0; i < n * k; i++) {
std::cin >> a[i];
}
std::sort(a.begin(), a.end());
std::vector<int> b;
for (int i = 0; i < n * k; i++) {
if (a[i] - a[0] <= l) {
b.push_back(a[i]);
}
}
if (b.size() < n) {
std::cout << "0\n";
return 0;
}
int num = 0;
i64 ans = 0;
std::vector<int> vis(b.size());
for (int i = 0; i < b.size(); num++, i += k) {
ans += b[i];
vis[i] = true;
}
for (int i = b.size() - 1; num < n && i > 0; i--) {
if (!vis[i]) {
ans += b[i];
num++;
}
}
std::cout << ans << "\n";
return 0;
}