Denso Create Programming Contest 2025(AtCoder Beginner Contest 413)

今天atcoder和cf连续两场,可惜两连战就两连跪。两场都是卡在简单题上了,总觉得思路应该没什么问题,就是某些小的点可能没考虑到。来看看这两场吧

A - Content Too Large

思路:给定n个物品的大小,以及一个背包的大小,问背包是否够大。这就是个水题,求个和即可判定。不过这次,又在YES和Yes大小写的问题上栽跟头了,屡教不改,总是在同一个坑摔更头可不是个好现象。3min第一WA,等到第二题做完,14min才转头再次提交,也是浪费了不少时间。

cpp 复制代码
/*
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

cpp 复制代码
/*
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

cpp 复制代码
/*
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

cpp 复制代码
/*
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

思路:给定一个数串,可以将其拆分成段,每段内可以进行翻转,求翻转后的最小串。

其实这一题也很好想,既然他说了这个段长,那么我们就按照这个段长来进行模拟。从小到大,每次对比相邻两个串进行合并,判断最小值在哪个串内,若在前串则不用动,若在后串,则分别将两串翻转后,合并,再将合并后的串翻转。

cpp 复制代码
/*
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过,比前一题还顺利。

相关推荐
Tony沈哲3 分钟前
macOS 上为 Compose Desktop 构建跨架构图像处理 dylib:OpenCV + libraw + libheif 实践指南
opencv·算法
程序员爱钓鱼7 分钟前
【无标题】Go语言中的反射机制 — 元编程技巧与注意事项
开发语言·qt
Frank学习路上17 分钟前
【IOS】XCode创建firstapp并运行(成为IOS开发者)
开发语言·学习·ios·cocoa·xcode
刘海东刘海东35 分钟前
结构型智能科技的关键可行性——信息型智能向结构型智能的转变(修改提纲)
人工智能·算法·机器学习
2301_805054561 小时前
Python训练营打卡Day59(2025.7.3)
开发语言·python
pumpkin845141 小时前
Rust 调用 C 函数的 FFI
c语言·算法·rust
lsx2024061 小时前
CSS 网页布局:从基础到进阶
开发语言
挺菜的1 小时前
【算法刷题记录(简单题)003】统计大写字母个数(java代码实现)
java·数据结构·算法
mit6.8241 小时前
7.6 优先队列| dijkstra | hash | rust
算法