PAT(乙级)2021年春季考试
比赛链接:https://pintia.cn/market/item/1371703238093053952
7-1 打印三角形拼图 (15 分)
题解
找规律。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
char up, down, diag;
cin >> n >> up >> down >> diag;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i < j) {
cout << up;
} else if (i == j) {
cout << diag;
} else {
cout << down;
}
}
cout << "\n";
}
return 0;
}
7-2 赌马 (20 分)
题解
按照题意排个序就可以了,考虑将 \(t_x = \frac{s_x}{v_x} < t_y = \frac{s_y}{v_y}\) 移项得到: \(s_x v_y < s_y v_x\) ,这样就只剩下整数间的运算,避免了浮点数的误差。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> num(n), s(n), v(n);
for (int i = 0; i < n; i++) {
cin >> num[i] >> s[i] >> v[i];
}
vector<int> p(n);
iota(p.begin(), p.end(), 0);
sort(p.begin(), p.end(), [&](int x, int y) {
if (s[x] * v[y] != s[y] * v[x]) {
return s[x] * v[y] < s[y] * v[x];
} else {
return num[x] < num[y];
}
});
for (int i = 0; i < 3; i++) {
cout << num[p[i]] << " \n"[i == 2];
}
return 0;
}
7-3 拼题 A 是真爱 (20 分)
题解
记录字母连续出现的区间,逐一截取判断即可。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s;
getline(cin, s);
s = ' ' + s + ' ';
vector<pair<int, int>> seg;
for (int i = 0; i < int(s.length()); i++) {
if (isalpha(s[i])) {
int j = i + 1;
while (j < int(s.length()) and isalpha(s[j])) {
++j;
}
seg.emplace_back(i, j - i);
i = j - 1;
}
}
int cnt = 0;
for (int i = 0; i < int(seg.size()); i++) {
string t = s.substr(seg[i].first, seg[i].second);
if (t == "pintia" or t == "Pintia") {
++cnt;
}
}
cout << cnt << "\n";
if (cnt == 0) {
cout << "wu gan" << "\n";
} else if (cnt <= 3) {
cout << "you ai" << "\n";
} else {
cout << "zhen ai la" << "\n";
}
return 0;
}
7-4 素数等差数列 (20 分)
题解
埃筛出所有素数然后枚举等差数列的前两项即可。
Tips
\(10^5\) 内有 \(9592\) 个素数,所以 \(O_{(n^2)}\) 的算法需要做一些优化。
代码
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 1e5 + 10;
vector<bool> is_prime(N, true);
void Init() {
is_prime[0] = is_prime[1] = false;
for (int i = 2; i < N; i++) {
if (not is_prime[i]) {
continue;
}
for (int j = i + i; j < N; j += i) {
is_prime[j] = false;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
Init();
int n, maxp;
cin >> n >> maxp;
vector<int> prime;
for (int i = 2; i <= maxp; i++) {
if (is_prime[i]) {
prime.push_back(i);
}
}
int a = -1, b = -1;
for (int i = 0; i < int(prime.size()); i++) {
for (int j = i + 1; j < int(prime.size()); j++) {
if ((n - 1) * (prime[j] - prime[i]) > prime.back()) { //优化一
continue;
}
bool ok = true;
for (int k = 2; k <= n - 1; k++) {
if (not binary_search(prime.begin(), prime.end(), prime[i] + k * (prime[j] - prime[i]))) {
ok = false;
break; //优化二
}
}
if (ok and prime[j] - prime[i] >= b - a) {
a = prime[i];
b = prime[j];
}
}
}
if (n == 1 or a == -1) {
cout << prime.back() << "\n";
} else {
for (int i = 0; i < n; i++) {
cout << a + i * (b - a) << " \n"[i == n - 1];
}
}
return 0;
}
7-5 实验室使用排期 (25 分)
题解
挺经典的一道贪心题,将区间按照右端点从小到大排序即可。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
scanf("%d", &n);
vector<int> l(n), r(n);
for (int i = 0; i < n; i++) {
int h1, m1, s1, h2, m2, s2;
scanf("%d:%d:%d %d:%d:%d", &h1, &m1, &s1, &h2, &m2, &s2);
l[i] = h1 * 3600 + m1 * 60 + s1;
r[i] = h2 * 3600 + m2 * 60 + s2;
}
vector<int> p(n);
iota(p.begin(), p.end(), 0);
sort(p.begin(), p.end(), [&](int x, int y) {
if (r[x] != r[y]) {
return r[x] < r[y];
} else {
return l[x] < l[y];
}
});
int ans = 1;
for (int i = 0; i < n; ) {
int j = i + 1;
while (j < n and l[p[j]] < r[p[i]]) {
++j;
}
if (j < n) {
++ans;
}
i = j;
}
printf("%d\n", ans);
return 0;
}