题目传送门
--------------------真还就是翻译场,英语四级阅读理解看到吐,我太菜了--------------------
A .Nastya and Rice
pro:问能否找出$n$个区间$[a - b, a + b]$内的数,满足和在区间$[c - d, c + d]$之内。
sol:最小的和是$n * (a - b)$,如果$n * (a - b) > c + d$,结果为"NO";最大的和是$n * (a + b)$,如果$n * (a + b) < c - d$,结果为"NO";剩下的情况结果都是"YES"。
- 数学
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int, int> PII; inline int read() { int n = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -f; c = getchar(); } while (c >= '0' && c <= '9') { n = 10 * n + (c ^ '0'); c = getchar(); } return f * n; } int main() { int t = read(); for (int i = 1; i <= t; i++) { int n = read(); bool ok = 1; int a = read(), b = read(), c = read(), d = read(); if ((a + b) * n < (c - d)) ok = 0; if ((a - b) * n > (c + d)) ok = 0; puts(ok ? "Yes" : "No"); } return 0; }
B .Nastya and Door
pro:找出一个长度为k的区间,使得区间内峰的数量是最大的,若两个区间内峰的数量相同,认为左边的区间为大。区间的两端不是峰。最后输出区间内峰的数量+1和区间的左端点。
sol:前缀和求出$[1, i]$之间峰的个数,对于询问$[i, i + k - 1]$有多少峰,由于两端不认为是峰,所以结果为$cnt[i + k - 2] - cnt[i]$。
- 前缀和
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MAXN = 200010; int val[MAXN], cnt[MAXN]; inline int read() { int n = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -f; c = getchar(); } while (c >= '0' && c <= '9') { n = 10 * n + (c ^ '0'); c = getchar(); } return f * n; } int main() { int t = read(); while (t--) { int n = read(), k = read(); for (int i = 1; i <= n; i++) val[i] = read(); for (int i = 2; i < n; i++) { cnt[i] = (val[i] > val[i - 1] && val[i] > val[i + 1]); cnt[i] += cnt[i - 1]; } int ans = 0, pos = 1; for (int i = 1; i + k - 1 <= n; i++) { if (cnt[i + k - 2] - cnt[i] > ans) { ans = cnt[i + k - 2] - cnt[i]; pos = i; } } printf("%d %d ", ans + 1, pos); } return 0; }
C .Nastya and Strange Generator
pro:可以进行数次操作,每次操作选一个$i$,然后按顺序取出$[i, n]$之内还没被取出的数,问能否构造给定排列。
sol:扫描一下整个数组,要么$a[i] = a[i - 1] + 1$,要么$a[i]$为当前最小值。否则不可构造。做好做,题意是真的难懂。
- 模拟
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MAXN = 200010; int a[MAXN]; inline int read() { int n = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -f; c = getchar(); } while (c >= '0' && c <= '9') { n = 10 * n + (c ^ '0'); c = getchar(); } return f * n; } int main() { int t = read(); while (t--) { int n = read(); bool ok = 1; int k = a[1] = read(); for (int i = 2; i <= n; i++) { a[i] = read(); if (a[i] == a[i - 1] + 1) continue; if (a[i] >= k) ok = 0; else k = a[i]; } puts(ok ? "Yes" : "No"); } return 0; }
D .Nastya and Scoreboard
pro:用一个$7$位二进制字符串表示一个电子数字,给出$n$个电子数字,这$n$个电子数字里有$m$根电子灯管本来该亮的但是没亮,求这$n$个电子数组组成的数最大是多少。允许前导零。
sol:先二进制压缩把字符串转成整型。然后用动态规划解决。$dp[i][j]$表示第$i$个电子数字到第$n$个电子数字一共有$j$根电子灯管该亮没亮的情况下,第$i$个电子数字的最大可能。
- 动态规划
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MAXN = 2010; inline int read() { int n = 0, f = 1; char c = getchar(); while (c < '0' || c > '1') { if (c == '-') f = -f; c = getchar(); } while (c >= '0' && c <= '1') { n = 2 * n + (c ^ '0'); c = getchar(); } return f * n; } int a[MAXN], d[] = {119, 18, 93, 91, 58, 107, 111, 82, 127, 123}; int dp[MAXN][MAXN]; int count(int i, int k) { // 把第i个数转成k需要点亮多少电子管 if ((a[i] | d[k]) != d[k]) return -1; int p = d[k] - a[i], cnt = 0; while (p != 0) { cnt ++; p -= p & -p; } return cnt; } int main() { int n, m; scanf("%d%d", &n, &m); memset(dp, -1, sizeof(dp)); for (int i = 1; i <= n; i++) a[i] = read(); for (int k = 0; k < 10; k++) { int cnt = count(n, k); if (cnt != -1) dp[n][cnt] = k; } for (int i = n - 1; i >= 1; i--) { for (int j = 0; j <= m; j++) { for (int k = 0; k < 10; k++) { int cnt = count(i, k); if (cnt == -1) continue; if (dp[i + 1][j - cnt] != -1) { dp[i][j] = k; } } } } if (dp[1][m] == -1) return 0 * puts("-1"); for (int i = 1; i <= n; i++) { printf("%d", dp[i][m]); m -= count(i, dp[i][m]); } return 0; }
------------------------------------------------------------分隔线------------------------------------------------------------
总结:错误提交多了点,不过如果不是罚时太高,可能做完三题就没动力做第四题了。第二题是wa2了两次之后看了讨论群才发现的bug,发现bug改了之后急于提交没去掉之前调试留下的输出语句又送了一发。第四题是大佬提醒了我用dp做,而且最后也是别人帮我找出了一个bug才过的。这两题都不算独立完成的,但是苟住了分。