2022广东工业大学新生程序设计竞赛
H. 马子哥的奖金
题意:从 n n n个数中取 k k k个,使得 k k k个数的乘积最大,输出 k k k个数的乘积模 1 e 9 + 7 1e9 + 7 1e9+7。
思路:负数两两一组,排个序贪心的取,如果绝对值最大的两个负数相乘大于最大的两个非负数,那么取两个负数,否则取一个最大的正数,直到把 k k k取完。(需要判一下边界条件)
坑点:没有正数且 k k k是奇数的时候,取的 k k k个数应是绝对值最小的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
const int mod = 1e9 + 7;
signed main() {
ios::sync_with_stdio(false);
int n, k, x;
cin >> n >> k;
int ans = 1;
vector<int> a, b;
int sza = 0;
for (int i = 1; i <= n; i++) {
cin >> x;
if (x >= 0) a.push_back(x), sza++;
else b.push_back(x);
}
int szb = n - sza;
sort(a.begin(), a.end(), greater<int>());
sort(b.begin(), b.end());
int cura = 0, curb = 0;
if (!sza && (k & 1)) {
for (int i = n - k; i < n; i++) {
ans = ans * b[i] % mod;
}
cout << ans << '\n';
return 0;
}
while (k) {
if (k > 1 && curb + 1 < szb && (cura + 1 >= sza || a[cura] * a[cura + 1] < b[curb] * b[curb + 1])) {
ans = b[curb] * b[curb + 1] % mod * ans % mod;
k -= 2;
curb += 2;
} else {
ans = a[cura] * ans % mod;
cura++;
k--;
}
}
cout << ans << '\n';
return 0;
}
I. 奇迹和魔法都是存在的
题意:给定一个长度为 n n n的数组,询问 m m m个区间,问操作任意次后最后剩下的数可能有几个。每次操作是把一个区间删除,留下第一个或最大的那个。
思路:我们需要手模一下,理解之后就很简单了,其实就是不小于第一个的都能留下来。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
signed main() {
ios::sync_with_stdio(false);
int n, m;
cin >> n >> m;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int l, r, ans;
while (m--) {
cin >> l >> r;
ans = 0;
for (int i = l; i <= r; i++) {
if (a[i] >= a[l]) ans++;
}
cout << ans << '\n';
}
return 0;
}
J. 狐臭的等比数列
题意:给定一个长度为 n n n的数组,问最少需要连续的多少项等比数列能包括所有 n n n个数。
思路:由于是等比数列,我们可以考虑公比最大是多少,而这个公比不一定是整数,我本来想重载一个 d o u b l e double doub