首页 > 其他分享 >ZZJC新生训练赛第五场题解

ZZJC新生训练赛第五场题解

时间:2024-10-18 20:24:14浏览次数:1  
标签:std 12 false ZZJC int 第五场 cin 题解 cout

A题

思路

题目要求构造一个相邻两项互质的长度为 n 的序列。可以直接选择输出从 1n 的自然数序列,因为相邻的自然数总是互质的。题目有多个测试用例,因此需要逐个处理输入,并输出对应结果。

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cout << i << " ";
        }
        cout << '\n';
    }
}

B题

思路

该题是一道模拟题,要求打印一个特定的图案。图案分为三部分:上半部分、中间部分、下半部分。每一部分的格式不同,但逻辑相对简单,可以通过逐层构造来完成。上半部分和下半部分是对称的,中间部分则是连续的星号和点的分布。

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    int cd = n * 4;
    
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n - i; j++) cout << ".";
        for (int j = 0; j < cd - 2 * (n - i); j++) cout << "*";
        for (int j = 0; j < n - i; j++) cout << ".";
        cout << endl;
    }
    
    for (int i = 0; i < 2 * n; i++) {
        for (int j = 0; j < n; j++) cout << "*";
        for (int j = 0; j < cd - 2 * n; j++) cout << ".";
        for (int j = 0; j < n; j++) cout << "*";
        cout << endl;
    }
    
    for (int i = n - 1; i >= 0; i--) {
        for (int j = 0; j < n - i; j++) cout << ".";
        for (int j = 0; j < cd - 2 * (n - i); j++) cout << "*";
        for (int j = 0; j < n - i; j++) cout << ".";
        cout << endl;
    }
}

C题

思路

这道题涉及树的删除边问题。当节点数为奇数时,无论如何删除边,都会有一个连通块的大小是奇数,因此无法满足题意,需要输出 -1。当节点数为偶数时,可以通过深度优先搜索(DFS)遍历树,从叶子节点向上遍历。当一个连通块的节点数为偶数时,删除该边并增加答案计数。最后,输出删除边的最小次数。

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    vector<vector<int>> g(n + 1);
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        g[u].emplace_back(v);
        g[v].emplace_back(u);        
    }
    
    int ans = 0;
    auto dfs = [&](auto&& self, int u, int fa) -> int {
        int cnt = 1;
        for (auto v : g[u]) {
            if (v != fa) {
                int op = self(self, v, u);
                cnt += op;
            }
        }
        ans += !(cnt & 1);
        return cnt;
    };
    
    dfs(dfs, 1, -1);
    
    if (n & 1) {
        cout << -1 << '\n';
    } else {
        cout << ans - 1 << "\n";
    }
}

D题

思路

我们需要在多个生物群系中选择一个作为庇护所,并计算所有生物群系的危险度之和。危险度的定义是:对于第 \(i\) 个生物群系,危险度为:

\begin{aligned}
f(i) = (x - i)^2 \times a_i
\end{aligned}

\(x\) 是选择作为庇护所的生物群系编号,\(a_i\) 是该生物群系的危险系数。

题目要求找出某个编号 \(x\) 使得所有生物群系的危险度之和最小。

设危险度之和的公式为:

\[S(x) = \sum_{i=1}^{n} f(i) = \sum_{i=1}^{n} (x - i)^2 \times a_i \]

展开每一项:

\[\begin{aligned} S(x) &= \sum_{i=1}^{n} \left( x^2 - 2xi + i^2 \right) a_i \\ &= x^2 \sum_{i=1}^{n} a_i - 2x \sum_{i=1}^{n} i a_i + \sum_{i=1}^{n} i^2 a_i \\ &= C x^2 - 2B x + A \end{aligned} \]

其中:

  • \(A = \sum_{i=1}^{n} i^2 a_i\)
  • \(B = \sum_{i=1}^{n} i a_i\)
  • \(C = \sum_{i=1}^{n} a_i\)

显然,\(S(x)\) 是关于 \(x\) 的二次函数。为了使 \(S(x)\) 最小,我们可以通过求导找到二次函数的顶点(直接用结论 \(-\frac{b}{2a}\) 也行)。

对 \(S(x)\) 关于 \(x\) 求导:

\(\frac{dS}{dx} = 2C x - 2B\)

令导数为零,求得最小值对应的 $ x $:

\(2C x - 2B = 0 \implies x = \frac{B}{C}\)

由于 \(x\) 必须是整数(生物群系的编号),我们只需要考虑邻近的整数值:

  • \(x_1 = \left\lfloor \frac{B}{C} \right\rfloor\)
  • \(x_2 = \left\lceil \frac{B}{C} \right\rceil\)

然后计算 \(S(x_1)\) 和 \(S(x_2)\),取其中 \(S(x)\) 最小的 \(x\) 作为答案,注意用求导的做法需要特判 \(C\) 是 \(0\) 的情况。

代码

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);

    i64 n;
    std::cin >> n;

    std::vector<i64> a(n + 1);
    i64 A = 0, B = 0, C = 0;
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        A += a[i] * i * i;
        B += a[i] * i;
        C += a[i];
    }

    if (C == 0) {
        std::cout << 0;
        return 0;
    }

    i64 x1 = std::min(n, std::max(1LL, B / C));
    i64 x2 = std::min(n, std::max(1LL, (B + C - 1) / C));

    i64 s1 = A - 2 * B * x1 + C * x1 * x1;
    i64 s2 = A - 2 * B * x2 + C * x2 * x2;

    std::cout << std::min(s1, s2);

    // 因为代码的时间复杂度已经是O(n),所以遍历所有的x也是可以接受的
    // i64 ans = 4e18;  // 初始设置一个极大值,保证能被后续结果更新
    // for (int i = 1; i <= n; i++) {
    //     // 计算每个 x=i 时的S(x)并更新最小值
    //     ans = std::min(ans, A - 2 * B * i + C * i * i);
    // }
    // std::cout << ans;
}

E题

思路

题目要求将小时部分从24小时制转换为12小时制,而分钟部分保持不变。如果小时数小于12,则输出 AM,否则输出 PM。当小时为 0 时,应转换为 12 AM。当小时大于 12 时,应减去 12 以转换为12小时制。

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int tt;
    for (cin >> tt; tt--;) {
        int a, b;
        cin >> a >> b;
        bool flag = true;
        if (a < 12) flag = false;
        if (a == 0) a = 12;
        if (a > 12) a = a - 12;
        cout << a << " " << b << " ";
        if (!flag) cout << "am\n";
        else cout << "pm\n";
    }
}

F题

思路

题目要求根据给定的条件判断能否满足某种关系。需要分类讨论:

  1. 如果 x > y,输出 "No"。
  2. 如果 n - m + x >= y,则输出 "Yes",否则输出 "No"。

代码

#include <bits/stdc++.h>
using namespace std;

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t;
    cin >> t;
    while (t--) {
        int n, m, x, y;
        cin >> n >> m >> x >> y;
        if (x > y) {
            cout << "No" << endl;
            continue;
        }
        if (n - m + x >= y)
            cout << "Yes" << endl;
        else    
            cout << "No" << endl;
    }
}

G题

思路

这是前缀和模板题。我们通过构建一个前缀和数组 ss[i],使得 ss[i] 表示数组前 i 个元素的和。然后对于每个询问 (l, r),可以在常数时间内得到区间 [l, r] 的和,公式为 ss[r] - ss[l - 1]

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    #define int long long
    int n, q;
    cin >> n >> q;
    vector<int> ar(n + 1), ss(n + 1);
    
    for (int i = 0; i < n; i++) {
        cin >> ar[i];
        ss[i + 1] = ar[i] + ss[i];
    }
    
    while (q--) {
        int l, r;
        cin >> l >> r;
        cout << ss[r] - ss[l - 1] << '\n';
    }
}

H题

思路

题目需要提取有效的输入字符并根据不同符号的情况判断输出结果。具体步骤是:

  1. 读取输入字符,提取 &, > 等符号及 01 的二进制字符。
  2. 如果出现 & 符号,进行逻辑与运算判断。
  3. 如果出现 > 符号,进行逻辑或运算判断。
  4. 否则,执行非运算。

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    bool flag1 = false, flag2 = false;
    char xp;
    vector<char> ar;
    
    while (cin >> xp) {
        if (xp == '&') flag1 = true;
        else if (xp == '>') flag2 = true;
        else if (xp >= '0' && xp <= '1') {
            ar.push_back(xp);
        }
    }
    
    if (flag1) {
        if (ar[0] == '1' && ar[1] == '1') cout << 1 << '\n';
        else cout << 0 << '\n';
    } 
    else if (flag2) {
        if (ar[0] == '1' || ar[2] == '1') cout << 1 << '\n';
        else cout << 0 << '\n';
    } 
    else {
        if (ar[0] == '1') cout << 0 << '\n';
        else cout << 1 << '\n';
    }
}

标签:std,12,false,ZZJC,int,第五场,cin,题解,cout
From: https://www.cnblogs.com/udiandianis/p/18473102

相关文章

  • 题解:[YNOI2019] 游戏
    ProblemLink[YNOI2019]游戏题外话第一眼,由乃?不打不打。第二眼,欸noi三个字母怎么是大写(才发现是云南省选)。题意题意简洁,不再赘述。Solution一眼看出概率dp,但如何似乎没思路?开始公式做题:设置状态+推转移式。\(Q1\):怎么设置状态?首先,思考一个问题:第\(k\)个人该怎么“......
  • 异常问题解决
    异常:java程序编译或运行过程中出现的问题Throwable:Error:表示非常严重的问题,自己无法解决的问题Exception:除了RuntimeException其它异常【编译时期异常】:一般指的是异常尚未处理就编译了RuntimeException【运行时期异......
  • PTA L1系列题解(C语言)(L1_081 -- L1_088)
    L1-081今天我要赢题目内容:2018年我们曾经出过一题,是输出“2018我们要赢”。今年是2022年,你要输出的句子变成了“我要赢!就在今天!”然后以比赛当天的日期落款。输入格式:本题没有输入。输出格式:输出分2行。在第一行中输出I'mgonnawin!Today!,在第二行中用年年年......
  • P1955 程序自动分析 题解
    P1955程序自动分析一道并查集的裸题,并查集存储传递性,后判断。主题思路十分简单,重点在于离散化与离线的处理。离散化,为什么会想到离散化呢,观察数据范围\(1<i,j<{10}^9\),数据范围过大,导致数组不可能开到\(1e9\)但是\(1<n<1e5\)考虑到每次输入只有两个数,若每个数都两两不同,......
  • 【题解】[Codechef] Beautiful Permutation
    传送门以此纪念我场切的dp。这种计数的类型一看就很dp的样子。考场上一开始设的dp状态是\(dp_{i,j,k_1,k_2,0/1}\)表示将前\(i\)个数分为\(j\)段,放了\(k_1\)个偶数,\(k_2\)个奇数,当前段为偶数段或奇数段的方案数。考虑如何转移,记\(cnt_0\)表示序列中可填入的偶数......
  • Codeforces Round 892 (Div. 2)题解记录
    题目链接:https://codeforces.com/contest/1859A.UnitedWeStand选最大的数即可注意题目输出格式 #include<iostream> #include<string.h> #include<map> #include<vector> #include<set> #include<unordered_set> #include<stack> #incl......
  • P5025 [SNOI2017] 炸弹 题解
    题意link.题解一个好想一点的正解。考虑到可能连锁爆炸,我们不能通过一个单纯的二分来解决问题。考虑dp。记\(f(i)\)为第\(i\)个点爆炸,最远能引爆到哪个坐标小于它的点。\(g(i)\)为第\(i\)个点爆炸,最远能引爆到哪个坐标大于它的点。我们以\(f\)为例,\(g\)可以通......
  • AT_nikkei2019_2_qual_c 题解
    blog。不会做结论题,怎么办???不会做结论题,怎么办???不会做结论题,怎么办???不妨对\(b\)排序,将\(a\)对应到相应的位置。那么题目有两个条件:#1:\(\foralla_i\leb_i\)。#2:操作限制。注意到\(n-1\)次操作就能完成对\(a\)排序。所以用\(n-2\)次操作可以将\(a\)变成一个Almos......
  • P9351 [JOI 2023 Final] Maze 题解
    Description给定一张\(R\timesC\)的地图,其中.可以走,而#不能走。一次操作可以将\(N\timesN\)的正方形范围内所有点变成.,给定起点和终点,求最少需要几次操作使得起点和终点连通(只能上下左右移动)。\(R\timesC\le6\times10^6\),\(N\leR\leC\)。Solution先考虑怎么......
  • CF571B-题解
    CF571B题意给定数组\(A\)和值\(k\),你可以重排\(A\)中的元素,使得\(\displaystyle\sum_{i=1}^{n-k}|A_i-A_{i+k}|\)最小。输出最小值。思路\(A_i,A_{i+k}\)就等同于在将\(i\)模\(k\)的意义上把\(A\)分为若干组贪心的想要使\(\displaystyle\sum_{i=1}^{n-k}|A_i-A......