题解按照题目顺序排列
A题
知识点:模拟,优先队列
初始时,CPU为空,第一个进程进入后,对于第二进程的选择,会以下选择:
1.当当前进程运行结束时,第二进程仍未进入,此时直接输出即可
2.若不足,此时已经处理了从当前到第二进程进入时间差值,减去后重新加入优先队列
此时剩下que内的进程,直接按照优先级排列即可,因为剩下的要么是已经被处理过的,要么是即将处理的
都已经与出现时间无关了
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
struct node {
i64 num, time, val, pri;
bool operator>(const node& y) const {
if (pri != y.pri) {
return y.pri > pri;
} else {
return time > y.time;
}
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
priority_queue<node, vector<node>, greater<node>> que;
vector<node> f;
i64 a, b, c, d;
i64 pre = 0;
while (cin >> a >> b >> c >> d) {
while (!que.empty() && pre + que.top().val <= b) {
cout << que.top().num << " " << que.top().val + pre << "\n";
pre += que.top().val;
que.pop();
}
if (!que.empty()) {
node x = que.top();
que.pop();
x.val = pre + x.val - b;
que.push(x);
}
que.push({a, b, c, d});
pre = b;
}
while (!que.empty()) {
cout << que.top().num << " " << pre + que.top().val << "\n";
pre += que.top().val;
que.pop();
}
return 0;
}
B题
知识点:二分
没啥好讲的,注意y是实数
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
constexpr double eps = 1e-14;
void solve() {
double y;
cin >> y;
double l = 0, r = 100;
auto check = [&](double x) -> double { return 2018 * x * x * x * x + 21 * x + 5 * x * x * x + 5 * x * x + 14; };
while (r - l > eps) {
double mid = (l + r) / 2;
if (check(mid) >= y) {
r = mid;
} else {
l = mid;
}
}
if (check(l) > y) {
cout << -1 << '\n';
} else {
cout << fixed << setprecision(4) << l << "\n";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
C题
知识点:前缀和
由于中位数要包括k,则考虑从数字k开始拓展
固定一边,处理大于k和小于k情况
此时遍历另一边,每次加上相反数量的情况个数即可\
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
int mid = 0;
vector<int> f(n + 1);
map<int, int> mp;
mp[0] = 1;
for (int i = 1; i <= n; i++) {
cin >> f[i];
if (f[i] == k) {
mid = i;
}
}
int ans = 0;
for (int i = mid - 1; i >= 1; i--) {
ans += (f[i] > k) ? 1 : -1;
mp[ans]++;
}
int res = mp[0];
ans = 0;
for (int i = mid + 1; i <= n; i++) {
ans += (f[i] > k) ? 1 : -1;
res += mp[-ans];
}
cout << res << "\n";
return 0;
}
D题
知识点:字符串
先转化为相同大写,加密即将原文向右移动k-'A'位,解密则相反
故模拟即可,注意需要保留大小写情况,负数情况\
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string a, b;
cin >> a >> b;
int n1 = a.size(), n2 = b.size();
for (int i = 0; i < n2; i++) {
char c = a[i % n1];
if (c <= 'z' && c >= 'a') {
c = c - 'a' + 'A';
}
char d = b[i];
if (d <= 'z' && d >= 'a') {
d = d - 'a' + 'A';
}
char res = ((d - 'A') - (c - 'A') + 26) % 26 + 'A';
if (b[i] <= 'z' && b[i] >= 'a') {
res = res - 'A' + 'a';
}
cout << res;
}
return 0;
}
E题
知识点:数学,模拟
由于k在1e5内,数据较大,在时间限制下,正常数据类型都无法存下,高精度无法在规定时间内完成
选择一些质数,计算输入的数模这些质数的值,再一个一个计算数列的每一项模这些质数的值,直到找到第一个完全一样的就是答案。
注意输入数据量较大,需要通过字符串来输入转化为数字,注意取模
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
using PII = pair<i64, i64>;
constexpr i64 MOD = 1e9 + 9;
constexpr int N = 1e5;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
vector<i64> f(N + 1);
f[1] = 1;
f[2] = 2;
map<i64, i64> mp;
mp[1] = 1, mp[2] = 2;
for (int i = 3; i <= N; i++) {
f[i] = (f[i - 1] + f[i - 2]) % MOD;
mp[f[i]] = i;
}
string s;
while (cin >> s) {
i64 ans = 0;
for (auto k : s) {
ans = (ans * 10 % MOD + k - '0') % MOD;
}
cout << mp[ans] << '\n';
}
return 0;
}
F题
参考训练赛2H题,原题\
G题
知识点:数学 签到题
void solve() {
int p, q;
cin >> p >> q;
if (p * q < 0) {
cout << p / q - 1 << '\n';
} else {
cout << p / q - (p % q == 0) << "\n";
}
}
H题
记录一下是不是每次都是复读即可
注意:由于题目问的是可能,所以未发言的都有可能是复读机
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<int> f(n + 1, -1);
string pre = "";
while (m--) {
int op;
string s;
cin >> op >> s;
if (s == pre && f[op] == -1) {
f[op] = 1;
}
if (s != pre) {
f[op] = 0;
}
pre = s;
}
vector<int> res;
for (int i = 1; i <= n; i++) {
if (f[i] == 1 || f[i]==-1) {
cout << i << " ";
}
}
return 0;
}
目录中的附加题 XOUR
知识点:位运算,并查集
需要异或后,由于异或相当于不进位加法,故保留除最后两位前的所有二进制位,其中4种皆与该数满足条件
故将一个数右移两位后,将所有情况加入并查集并从小到大排序,再按照祖宗依次输出即可
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
void solve() {
int n;
cin >> n;
vector<i64> f(n + 1);
map<i64, vector<i64>> mp;
for (int i = 1; i <= n; i++) {
cin >> f[i];
mp[f[i] >> 2LL].push_back(f[i]);
}
map<i64, int> cnt;
for (auto& [l, p] : mp) {
cnt[l] = 0;
sort(p.begin(), p.end());
}
for (int i = 1; i <= n; i++) {
i64 t = f[i] >> 2LL;
cout << mp[t][cnt[t]++] << " ";
}
cout << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}