Denso Create Programming Contest 2025(AtCoder Beginner Contest 413)
今天atcoder和cf连续两场,可惜两连战就两连跪。两场都是卡在简单题上了,总觉得思路应该没什么问题,就是某些小的点可能没考虑到。来看看这两场吧
A - Content Too Large
思路:给定n个物品的大小,以及一个背包的大小,问背包是否够大。这就是个水题,求个和即可判定。不过这次,又在YES和Yes大小写的问题上栽跟头了,屡教不改,总是在同一个坑摔更头可不是个好现象。3min第一WA,等到第二题做完,14min才转头再次提交,也是浪费了不少时间。
/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int n, m;cin >> n >> m;int sum = 0;for (int i = 0; i < n; i++) {int a;cin >> a;sum += a;}if (sum > m) {cout << "No" << endl;} else {cout << "Yes" << endl;}return 0;
}
B - cat 2
思路:给定n个字符串,要求字符串俩俩拼接,求能拼接出多少种不同的新字符串
水题一个,存储字符串然后拼接后往set里扔。一开始是读字符串没读出来,后面又忘记了两个字符串可以前后拼接两次,反正小问题不断,13min才ac,本题用时10min
/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;const int MAXN = 105;string v[MAXN];int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int n;cin >> n;for (int i = 0; i < n; i++) {cin >> v[i];}set<string> col;for (int i = 0; i < n - 1; i++) {for (int j = i + 1; j < n; j++) {string s = v[i] + v[j];col.insert(s);s = v[j] + v[i];col.insert(s);// cout << i << "*" << j << "*" << v[i] << "*" << v[j] << "*" << s << "*" << col.size() << endl;}}cout << col.size() << endl;return 0;
}
C - Large Queue
思路:给定入队和出队操作,入队可以一次入c个相同的数,出队可以连续出k个数并求和,要求模拟过程。这也是水题,用两个数组分别记录队列重复的数量和重复值,出队的时候修改每一位的剩余值并求和就可以了,细节点注意一下变量值的维护,避免死循环,真的离谱,还能犯这种错。27min搞定,本题用时13min
/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;const int MAXN = 2e5 + 5;;typedef long long ll;int cc[MAXN];
int xx[MAXN];int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int q;cin >> q;int current = 0, pos = 0;;while (q--) {int p;cin >> p;if (p == 1) {int c, x;cin >> c >> x;cc[pos] = c;xx[pos++] = x;} else {int k;cin >> k;ll re = 0;while (k > 0) {if (cc[current] <= k) {re += (ll) xx[current] * (ll) cc[current];k -= cc[current];current++;} else {re += (ll) xx[current] * (ll) k;cc[current] -= k;k = 0;}}cout << re << endl;}}return 0;
}
D - Make Geometric Sequence
思路:给定n个数,问这n个数能否成为等比数列。卡题卡题疯狂卡题,第一次提交只花费了21min,但是卡题卡了整整46min,一直卡到比赛结束还没卡出来,看看吧,这题到底错哪里了。
这题我的思路就是先按照绝对值排序,排完后,求相邻两数的公比,并判别符号,最后特殊注意一下,所有数绝对值都一样的场景,要求要么符号都一样,要么不同符号差最大为1。
看不出来这题哪里出问题了,重写。这题的重心就在绝对值相同和绝对值不同等差两种情况。
于是先特判绝对值相同的场景,然后对负数进行计数
针对常规场景,有两个小技巧,一是可以重写cmp函数,做到按照绝对值排序切不丢失原有符号。二是在判断等比的时候,化除法为乘法,可以避免精度丢失,妥妥AC
/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;const int MAXN = 2e5 + 5;int a[MAXN];typedef long long ll;bool cmp(int a, int b) {return abs(a) < abs(b);
}int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int t;cin >> t;while (t--) {int n;cin >> n;cin >> a[0];bool allSame = true;bool ok = true;int minus = a[0] < 0 ? 1 : 0;for (int i = 1; i < n; i++) {cin >> a[i];if (abs(a[i]) != abs(a[0])) {allSame = false;}if (a[i] < 0) {minus++;}}sort(a, a + n, cmp);if (allSame) {if (n % 2 == 0 && (minus != n / 2 && minus != n && minus != 0)) {ok = false;}if (n % 2 == 1 && (minus != n / 2 && minus != n / 2 + 1 && minus != n && minus != 0)) {ok = false;}} else {for (int i = 2; i < n; i++) {if ((ll) a[i - 2] * (ll) a[i] != (ll) a[i - 1] * (ll) a[i - 1]) {ok = false;break;}}}if (ok) {cout << "Yes" << endl;} else {cout << "No" << endl;}}return 0;
}const double eps = 1e-5;set<int> maset;
set<int> allset;int mainWA() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int t;cin >> t;while (t--) {int n;cin >> n;maset.clear();int mdc = 0;int mda = -1;bool ok = true;bool hasSame = false;for (int i = 0; i < n; i++) {cin >> a[i];if (a[i] < 0) {a[i] = -a[i];if (allset.contains(a[i])) {if (hasSame == false && maset.contains(a[i])) {// 当首个是负数第二个也是负数时,补上首个的负数mdc++;}if (mda == -1 || mda == a[i]) {mda = a[i];mdc++;} else {ok = false;}hasSame = true;} else {maset.insert(a[i]);}} else {if (allset.contains(a[i])) {if (hasSame == false && maset.contains(a[i])) {// 当首个是负数第二个是正数时,补上首个的负数mdc++;}hasSame = true;}}allset.insert(a[i]);}if (ok) {sort(a, a + n);int a0 = a[0];int a1 = a[1];double diff = (double) a1 / (double) a0;bool m0 = maset.contains(a0);bool m1 = maset.contains(a1);bool samem = m1 == m0;for (int i = 2; i < n; i++) {int ai = a[i];bool mi = maset.contains(ai);double diffa = diff - (double) ai / (double) a1;if (diffa > eps || diffa < -eps) {ok = false;break;}if (samem != (mi == m1)) {ok = false;break;}a1 = ai;m1 = mi;}}if (ok && mdc > 0) {if (n % 2 == 0 && (mdc != n / 2 && mdc != n)) {ok = false;}if (n % 2 == 1 && (mdc != n / 2 && mdc != n / 2 + 1 && mdc != n)) {ok = false;}}if (ok) {cout << "Yes" << endl;} else {cout << "No" << endl;}}return 0;
}// 2
// 4
// 1 1 -1 1
// 2
// -2 -2
E - Reverse 2^i
思路:给定一个数串,可以将其拆分成段,每段内可以进行翻转,求翻转后的最小串。
其实这一题也很好想,既然他说了这个段长,那么我们就按照这个段长来进行模拟。从小到大,每次对比相邻两个串进行合并,判断最小值在哪个串内,若在前串则不用动,若在后串,则分别将两串翻转后,合并,再将合并后的串翻转。
/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;const int MAXN = 3e5 + 5;int p[MAXN];void compareAndReverse(int pos, int len) {// cout << "len=" << len << "pos=" << pos << " ";// for (int i = 0; i < 2 * len; i++) {// cout << p[i] << " ";// }// cout << endl;int min1 = p[pos];int min2 = p[pos + len];for (int i = 1; i < len; i++) {min1 = min(min1, p[pos + i]);min2 = min(min2, p[pos + len + i]);}if (min1 > min2) {reverse(p + pos, p + pos + len);reverse(p + pos + len, p + pos + len + len);reverse(p + pos, p + pos + len + len);}// for (int i = 0; i < 2 * len; i++) {// cout << p[i] << " ";// }// cout << "after" << endl;
}int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int t;cin >> t;while (t--) {int n;cin >> n;int maxn = 1;for (int i = 0; i < n; i++) {maxn *= 2;}for (int i = 0; i < maxn; i++) {cin >> p[i];}for (int len = 1; len < maxn; len *= 2) {for (int pos = 0; pos + len * 2 <= maxn; pos += len * 2) {compareAndReverse(pos, len);}}for (int i = 0; i < maxn; i++) {cout << p[i] << " ";}cout << endl;}return 0;
}
这一题一开始被边界的问题闹得晕晕乎乎,实际数组大小其实为指数级,但由于上限限制了最大数量级避免的数组不会越界。还是写的时候需要脑子清楚呀。这一题比赛结束后36min过,比前一题还顺利。