草庐IT

第十三届蓝桥杯大赛软件赛决赛(C/C++ 大学B组)

肖有量 2023-04-20 原文

蓝桥杯 2022年国赛真题
C/C++ 大学B组


   更新中…


试题 A: 2022

本题总分: 5 5 5


【问题描述】

  将 2022 2022 2022 拆分成 10 10 10 个互不相同的正整数之和,总共有多少种拆分方法?

  注意交换顺序视为同一种方法,例如 2022 = 1000 + 1022 2022 = 1000 + 1022 2022=1000+1022 2022 = 1022 + 1000 2022 = 1022 + 1000 2022=1022+1000 就视为同一种方法。

【答案提交】

  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个由大写字母组成的字符串,在提交答案时只填写这个字符串,填写多余的内容将无法得分。


379187662194355221


k 部分互异分拆数


  定义 p d k n pd_kn pdkn n n n 分拆成 k k k 个不同的部分的方案数,即下列方程 : : n = r 1 + r 2 + ⋯ + r k , r 1 > r 2 > ⋯ > r k ≥ 1 n = r_1 +r_2 + \cdots +r_k,\quad r_1 > r_2 >\cdots>r_k \geq 1 n=r1+r2++rk,r1>r2>>rk1  的解的数量,两边同时减去 k k k : : n − k = d 1 + d 2 + ⋯ + d k , d 1 > d 2 > ⋯ > d k ≥ 0 , n - k = d_1 +d_2 + \cdots +d_k,\quad d_1 > d_2 >\cdots>d_k \geq 0, nk=d1+d2++dk,d1>d2>>dk0  由于 d i d_i di 互异,故仅能有一个部分为 0 0 0,以此为界,划分成 : : n − k = d 1 + d 2 + ⋯ + d k − 1 + 0 , d 1 > d 2 > ⋯ > d k ≥ 0 , n − k = g 1 + g 2 + ⋯ + g k , g 1 > g 2 > ⋯ > g k ≥ 1 , n - k = d_1 +d_2 + \cdots +d_{k-1} + 0,\quad d_1 > d_2 >\cdots>d_k \geq 0,\\n - k = g_1 +g_2 + \cdots +g_k,\quad g_1 > g_2 >\cdots>g_k \geq 1, nk=d1+d2++dk1+0,d1>d2>>dk0nk=g1+g2++gk,g1>g2>>gk1  两部分,显然有递推式 : : p d k n = p d k − 1 ( n − k ) + p d k ( n − k ) . pd_kn=pd_{k-1}(n-k) + pd_k(n-k). pdkn=pdk1(nk)+pdk(nk).

#include <stdio.h>

const int N = 2022, k = 10;

long long pd[N + 1][k + 1]{1};

int main() {
    for (int i = 1; i <= N; ++i)
        for (int j = 1; j <= k; ++j)
            if (i >= j) pd[i][j] = pd[i - j][j] + pd[i - j][j - 1];
    printf("%lld", pd[N][k]);
}

  上来就这么劲爆的吗,难度


试题 B: 钟表

本题总分: 5 5 5


【问题描述】

  在 12 12 12 小时制的钟表中,有分针、时针、秒针来表示时间。记分针和时针之间的夹角度数为 A ( 0 ≤ A ≤ 180 ) A(0 ≤ A ≤ 180) A0A180、分针和秒针之间的夹角度数为 B ( 0 ≤ B ≤ 180 ) B(0 ≤ B ≤ 180) B0B180。而恰好在 s s s f f f m m m 秒时,满足条件 A = 2 B A = 2B A=2B 0 ≤ s ≤ 6 ; 0 ≤ f < 60 ; 0 ≤ m < 60 0 ≤ s ≤ 6;0≤ f < 60;0≤m < 60 0s60f<600m<60,请问 s , f , m s, f,m s,f,m 分别是多少。

  注意时针、分针、秒针都围绕中心匀速转动。

  提交格式为三个由一个空格隔开的整数,分别表示 s , f , m s, f,m s,f,m。如 3   11   58 3\ 11\ 58 3 11 58 表示 3 3 3 11 11 11 58 58 58 秒。

【答案提交】

  这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为三个由一个空格隔开的整数,在提交答案时只填写为三个由一个空格隔开的整数,填写多余的内容将无法得分。


4 48 0


  为了一定程度上的运算简便,这里周角为 60 60 60 度,

  然后 B F \small \rm BF BF 就完了。

#include <stdio.h>

double fabs(double x) { return x > 0 ? x : -x; }

double abs(double angle) {
    angle = fabs(angle);
    if (angle > 30) return 60 - angle;
    return angle;
}

int main() {
    for (int s = 0; s <= 6; ++s)
        for (int f = 0; f < 60; ++f)
            for (int m = 0; m < 60; ++m) {
                double second = m;
                double minute = f + second / 60;
                double hour = (s * 60 + minute) / 12;
                double B = abs(minute - second);
                double A = abs(minute - hour);
                if (fabs(A - 2 * B) < 1e-10)
                    printf("%d %d %d\n", s, f, m);
            }
}

  还好我的好 b r o \small\rm bro bro 告诉我 0   0   0 0\ 0\ 0 0 0 0 是作废答案,

  不然我就直接填了。

  其实也可以类似程序中计算角度的过程来列出三元方程组,算的还快一点。


试题 C: 卡牌

时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 256.0 M B 256.0\mathrm{MB} 256.0MB 本题总分: 10 10 10


【问题描述】

  这天,小明在整理他的卡牌。

  他一共有 n n n 种卡牌,第 i i i 种卡牌上印有正整数数 i ( i ∈ [ 1 , n ] ) i(i \in [1, n]) i(i[1,n]),且第 i i i 种卡牌现有 a i a_i ai 张。

  而如果有 n n n 张卡牌,其中每种卡牌各一张,那么这 n n n 张卡牌可以被称为一套牌。小明为了凑出尽可能多套牌,拿出了 m m m 张空白牌,他可以在上面写上数i,将其当做第 i i i 种牌来凑出套牌。然而小明觉得手写的牌不太美观,决定第 i i i 种牌最多手写 b i b_i bi 张。

  请问小明最多能凑出多少套牌?

【输入格式】

  输入共 3 3 3 行,第一行为两个正整数 n , m n, m n,m

  第二行为 n n n 个正整数 a 1 , a 2 , ⋯   , a n a_1, a_2, \cdots, a_n a1,a2,,an

  第三行为 n n n 个正整数 b 1 , b 2 , ⋯   , b n b_1, b_2, \cdots, b_n b1,b2,,bn

【输出格式】

  一行,一个整数表示答案。

【样例输入】

4 5
1 2 3 4
5 5 5 5

【样例输出】

3

【样例说明】

  这 5 5 5 张空白牌中,拿 2 2 2 张写 1 1 1,拿 1 1 1 张写 2 2 2,这样每种牌的牌数就变为了 3 , 3 , 3 , 4 3, 3, 3, 4 3,3,3,4,可以凑出 3 3 3 套牌,剩下 2 2 2 张空白牌不能再帮助小明凑出一套。

【评测用例规模与约定】

  对于 30 % 30\% 30% 的数据,保证 n ≤ 2000 n ≤ 2000 n2000
  对于 100 % 100\% 100% 的数据,保证 n ≤ 2 × 1 0 5 ; a i , b i ≤ n ; m ≤ n 2 n ≤ 2 × 10^5; a_i, b_i ≤ n; m ≤ n^2 n2×105;ai,bin;mn2


#include <stdio.h>

const int N = 2 * 1e5;

int n, A[N], B[N];

long long m;

int main() {
    scanf("%d %lld", &n, &m);
    for (int i = 0; i < n; ++i) scanf("%d", A + i);
    for (int i = 0; i < n; ++i) scanf("%d", B + i);
    int l = 0, r = 2 * n;
    while (l < r) {
        int flag = 1, mid = l + r + 1 >> 1;
        long long buf = m;
        for (int i = 0; i < n; ++i) {
            if (A[i] >= mid) continue;
            if (A[i] + B[i] < mid || mid - A[i] > buf) {
                flag = 0;
                break;
            }
            buf -= mid - A[i];
        }
        if (flag) l = mid; else r = mid - 1;
    }
    printf("%d", l);
}

  二分判定答案的模板。


试题 D: 最大数字

时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 256.0 M B 256.0\mathrm{MB} 256.0MB 本题总分: 10 10 10


【问题描述】

  给定一个正整数 N N N。你可以对 N N N 的任意一位数字执行任意次以下 2 2 2 种操作 : :

   1. 1. 1. 将该位数字加 1 1 1。如果该位数字已经是 9 9 9,加 1 1 1 之后变成 0 0 0
   2. 2. 2. 将该位数字减 1 1 1。如果该位数字已经是 0 0 0,减 1 1 1 之后变成 9 9 9

  你现在总共可以执行 1 1 1 号操作不超过 A A A 次, 2 2 2 号操作不超过 B B B 次。

  请问你最大可以将 N N N 变成多少?

【输入格式】

  第一行包含 3 3 3 个整数 : : N , A , B N, A, B N,A,B

【输出格式】

  一个整数代表答案。

【样例输入】

123 1 2

【样例输出】

933

【样例说明】

  对百位数字执行 2 2 2 2 2 2 号操作,对十位数字执行 1 1 1 1 1 1 号操作。

【评测用例规模与约定】

  对于 30 % 30\% 30% 的数据, 1 ≤ N ≤ 100 ; 0 ≤ A , B ≤ 10 1 ≤ N ≤ 100; 0 ≤ A, B ≤ 10 1N100;0A,B10
  对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1 0 17 ; 0 ≤ A , B ≤ 100 1 ≤ N ≤ 10^{17}; 0 ≤ A, B ≤ 100 1N1017;0A,B100


#include <stdio.h>

char N[20];

long long ans = 0;

int A, B;

inline int min(int a, int b) { return a < b ? a : b; }

void dfs(int i, long long val) {
    if (N[i]) {
        int a = min(A, '9' - N[i]);
        A -= a;
        dfs(i + 1, val * 10 + N[i] + a - '0');
        A += a;
        if (N[i] - '0' < B) {
            int b = N[i] - '0' + 1;
            B -= b;
            dfs(i + 1, val * 10 + 9);
            B += b;
        }
    } else if (val > ans) ans = val;
}

int main() { scanf("%s %d %d", N, &A, &B), dfs(0, 0), printf("%lld", ans); }

  看一眼数据范围就知道,贪心暴搜。


试题 E: 出差

时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 256.0 M B 256.0\mathrm{MB} 256.0MB 本题总分: 15 15 15


【问题描述】

   A \rm A A 国有 N N N 个城市,编号为 1 ⋯ N \rm 1 \cdots N 1N。小明是编号为 1 1 1 的城市中一家公司的员工,今天突然接到了上级通知需要去编号为 N \rm N N 的城市出差。

  由于疫情原因,很多直达的交通方式暂时关闭,小明无法乘坐飞机直接从城市 1 1 1 到达城市 N \rm N N,需要通过其他城市进行陆路交通中转。小明通过交通信息网,查询到了 M M M 条城市之间仍然还开通的路线信息以及每一条路线需要花费的时间。

  同样由于疫情原因,小明到达一个城市后需要隔离观察一段时间才能离开该城市前往其他城市。通过网络,小明也查询到了各个城市的隔离信息。(由于小明之前在城市 1 1 1,因此可以直接离开城市 1 1 1,不需要隔离)

  由于上级要求,小明希望能够尽快赶到城市 N \rm N N,因此他求助于你,希望你能帮他规划一条路线,能够在最短时间内到达城市 N \rm N N

【输入格式】

  第 1 1 1 : : 两个正整数 N , M N, M N,M N N N 表示 A \rm A A 国的城市数量, M M M 表示未关闭的路线数量

  第 2 2 2 : : N N N 个正整数,第 i i i 个整数 C i C_i Ci 表示到达编号为 i i i 的城市后需要隔离的时间

  第 3 ⋯ M + 2 3 \cdots M + 2 3M+2 : : 每行 3 3 3 个正整数, u , v , c u, v, c u,v,c,表示有一条城市 u u u 到城市 v v v 的双向路线仍然开通着,通过该路线的时间为 c c c

【输出格式】

  第 1 1 1 : : 1 1 1 个正整数,表示小明从城市 1 1 1 出发到达城市 N \rm N N 的最短时间(到达城市 N \rm N N,不需要计算城市 N \rm N N 的隔离时间)

【样例输入】

4 4
5 7 3 4
1 2 4
1 3 5
2 4 3
3 4 5

【样例输出】

13

【样例说明】

   [ 1 ( 5 ) ] − − 4 − − [ 2 ( 7 ) ] [1(5)] --4-- [2(7)] [1(5)]4[2(7)]
    ∣ ∣ |\qquad\qquad\qquad\quad|
    ∣ ∣ |\qquad\qquad\qquad\quad|
    5      3 5\qquad\qquad\qquad\ \:\:3 5 3
    ∣ ∣ |\qquad\qquad\qquad\quad|
    ∣ ∣ |\qquad\qquad\qquad\quad|
   [ 3 ( 3 ) ] − − 5 − − [ 4 ( 4 ) ] [3(3)] --5-- [4(4)] [3(3)]5[4(4)]

  路线 1 1 1 : : 1 − > 2 − > 4 1 -> 2 -> 4 1>2>4,时间为 4 + 7 4+7 4+7(隔离) + 3 = 14 +3=14 +3=14
  路线 2 2 2 : : 1 − > 3 − > 4 1 -> 3 -> 4 1>3>4,时间为 5 + 3 5+3 5+3(隔离) + 5 = 13 +5=13 +5=13

【评测用例规模与约定】

  对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1000 , 1 ≤ M ≤ 10000 , 1 ≤ C i ≤ 200 , 1 ≤ u , v ≤ N , 1 ≤ c ≤ 1000 1 ≤ N ≤ 1000 , 1 ≤ M ≤ 10000, 1 ≤ C_i ≤ 200, 1 ≤ u, v ≤ N, 1 ≤ c ≤ 1000 1N1000,1M10000,1Ci200,1u,vN,1c1000


#include <stdio.h>
#include <utility>
#include <queue>

const int N = 1e3 + 1, M = 4 * 1e4 + 9;

int linked[M], next[M], ver[M], val[M], cur = 0;

inline void link(int u, int v, int k) { ++cur, next[cur] = linked[u], linked[u] = cur, ver[cur] = v, val[cur] = k; }

std::priority_queue<std::pair<int, int>> q;

int n, m, u, v, c, C[N], dist[N];

bool visited[N];

int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i)
        scanf("%d", C + i), dist[i] = 0x3f3f3f3f;
    C[1] = 0;
    while (m--) {
        scanf("%d %d %d", &u, &v, &c);
        link(u, v, C[u] + c);
        link(v, u, C[v] + c);
    }
    dist[1] = 0;
    q.push({0, 1});
    while (q.size()) {
        u = q.top().second, q.pop();
        if (visited[u]) continue;
        visited[u] = 1;
        for (cur = linked[u]; cur; cur = next[cur])
            if (dist[ver[cur]] > dist[u] + val[cur]) {
                dist[ver[cur]] = dist[u] + val[cur];
                q.push({-dist[ver[cur]], ver[cur]});
            }
    }
    printf("%d", dist[n]);
}

  模板 × 3 \times 3 ×3


试题 F: 费用报销

时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 256.0 M B 256.0\mathrm{MB} 256.0MB 本题总分: 15 15 15


【问题描述】

  小明在出差结束后返回了公司所在的城市,在填写差旅报销申请时,粗心的小明发现自己弄丢了出差过程中的票据。

  为了弥补小明的损失,公司同意小明用别的票据进行报销,但是公司财务要求小明提交的票据中任意两张的日期差不小于 K K K 天,且总金额不得超过实际差旅费用 M M M

  比如财务要求 K = 7 K = 7 K=7 时,若小明提交了一张 1 1 1 8 8 8 日的票据,小明就不能提交 1 1 1 2 2 2 日至 1 1 1 14 14 14 日之间的其他票据, 1 1 1 1 1 1 日及之前和 1 1 1 15 15 15 日及之后的票据则可以提交。

  公司的同事们一起给小明凑了 N N N 张票据,小明现在想要请你帮他整理一下,从中选取出符合财务要求的票据,并使总金额尽可能接近 M M M

  需要注意,由于这些票据都是同一年的,因此 12 12 12 月底的票据不会影响到 1 1 1 月初票据的提交。这一年不是闰年。

【输入格式】

  第 1 1 1 : : 3 3 3 个整数, N , M , K N, M, K N,M,K

  第 2 ⋯ N + 1 2 \cdots N + 1 2N+1 : : 每行 3 3 3 个整数 m i , d i , v i m_i, d_i, v_i mi,di,vi,第 i + 1 i + 1 i+1 行表示第 i i i 张票据时间的月份 m i m_i mi 和日期 d i d_i di v i v_i vi 表示该票据的面值

【输出格式】

  第 1 1 1 : : 1 1 1 个整数,表示小明能够凑出的最大报销金额

【样例输入】

4 16 3
1 1 1
1 3 2
1 4 4
1 6 8

【样例输出】

10

【样例说明】

  选择 1 1 1 3 3 3 日和 1 1 1 6 6 6 日的票据

【评测用例规模与约定】

  对于 100 % 100\% 100% 的评测用例, 1 ≤ N ≤ 1000 , 1 ≤ M ≤ 5000 , 1 ≤ K ≤ 50 , 1 ≤ m i ≤ 12 , 1 ≤ d i ≤ 31 , 1 ≤ v i ≤ 400 1 ≤ N ≤ 1000, 1 ≤ M ≤ 5000, 1 ≤ K ≤ 50, 1 ≤ m_i ≤ 12, 1 ≤ d_i ≤ 31, 1 ≤ v_i ≤ 400 1N1000,1M5000,1K50,1mi12,1di31,1vi400
  日期保证合法。


#include <stdio.h>
#include <algorithm>
#include <utility>

const int max_N = 1e3 + 1, max_M = 5 * 1e3 + 1;

const int offset[]{ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };

std::pair<int, int> bill[max_N];

bool dp[max_N][max_M]{1};

int N, M, K, m, d, v;

int main() {
    scanf("%d %d %d", &N, &M, &K);
    for (int i = 1; i <= N; ++i)
        scanf("%d %d %d", &m, &d, &v),
        bill[i] = {offset[m] + d, v};
    std::sort(bill + 1, bill + N + 1);
    for (int i = 1, k = 0; i <= N; ++i) {
        while (bill[i].first - bill[k + 1].first >= K) ++k;
        for (int j = M; j >= bill[i].second; --j)
            dp[i][j] = dp[i - 1][j] | dp[k][j - bill[i].second];
        for (int j = bill[i].second - 1; ~j; --j) dp[i][j] = dp[i - 1][j];
    }
    for (int i = M; ~i; --i)
        if (dp[N][i]) {
            printf("%d", i);
            return 0;
        }
}

  模板 × 4 \times 4 ×4,还是 0 0 0 - 1 1 1 背包。


试题 G: 故障

时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 256.0 M B 256.0\mathrm{MB} 256.0MB 本题总分: 20 20 20


【问题描述】

  在软件或系统开发中,我们会遇到各种各样的故障。为了从故障现象反推故障原因,工程师们会总结一种叫做相关性矩阵的二维表格,来表示故障原因与故障现象之间的关系。比如 : :

+ − − − + − − − + − − − + − − − + − − − + − − − + \scriptstyle{+---+---+---+---+---+---+} +++++++
∣ ∣      1     ∣      2     ∣      3     ∣      4     ∣      5     ∣ \scriptstyle\: |\quad\quad| \textstyle{\ \ \: 1\ \ \ }\scriptstyle| \textstyle{\ \ \: 2\ \ \ }\scriptstyle|\textstyle{\ \ \: 3\ \ \ }\scriptstyle|\textstyle{\ \ \: 4\ \ \ }\scriptstyle|\textstyle{\ \ \: 5\ \ \ }\scriptstyle|   1     2     3     4     5   
+ − − − + − − − + − − − + − − − + − − − + − − − + \scriptstyle{+---+---+---+---+---+---+} +++++++
∣      A     ∣ ∣      x      ∣      x      ∣      x      ∣ ∣ \scriptstyle\:| \textstyle{\ \: \: \small\rm A\: \: \: }\scriptstyle|\qquad\scriptstyle| \textstyle{\ \ \: \rm x\: \ \ }\scriptstyle|\textstyle{\ \ \: \rm x\: \ \ }\scriptstyle|\textstyle{\ \ \: \rm x\: \ \ }\scriptstyle|\qquad\scriptstyle|  A  x    x    x  
+ − − − + − − − + − − − + − − − + − − − + − − − + \scriptstyle{+---+---+---+---+---+---+} +++++++
∣      B     ∣     x      ∣ ∣      x      ∣ ∣ ∣ \scriptstyle\:|\textstyle{\ \: \: \small\rm B\: \: \: }\scriptstyle|\textstyle{\ \ \ \rm x \: \ \ }\scriptstyle|\qquad|\textstyle{\ \ \: \rm x\:\ \ }\scriptstyle|\qquad|\qquad|  B   x    x  
+ − − − + − − − + − − − + − − − + − − − + − − − + \scriptstyle{+---+---+---+---+---+---+} +++++++
∣      C     ∣ ∣ ∣ ∣      x      ∣      x     ∣ \scriptstyle\:|\textstyle{\ \: \: \small \rm C\: \: \: }\scriptstyle|\qquad|\qquad|\qquad\scriptstyle|\textstyle{\ \ \: \rm x \: \ \ }\scriptstyle|\textstyle{\ \ \:\rm x \ \ \ }\scriptstyle|  C  x    x   
+ − − − + − − − + − − − + − − − + − − − + − − − + \scriptstyle{+---+---+---+---+---+---+} +++++++

  其中每行表示一种故障原因,每一列表示一种故障现象。该矩阵表示故障原因 A A A 可能产生故障现象 2 、 3 、 4 2、3、4 234,故障原因 B B B 可能产生故障现象 1 、 3 1、3 13

  在实际开发过程中,如果出现了故障原因,工程师就可以根据故障现象,去计算每种故障原因产生的概率,并按照概率大小对故障原因进行排查,以达到快速定位故障原因的目的。

  现在,我们假设系统开发中同一时间只会出现一种故障原因,并且故障原因引起各故障现象是独立事件。举个例子来说 : :

  假设系统现在发生了故障原因 A A A,有 1 3 \frac 13 31 的概率出现故障现象 2 2 2,有 1 4 \frac 14 41 的概率出现故障现象 3 3 3,有 1 2 \frac 12 21 的概率出现故障现象 4 4 4。由于 3 3 3 种现象是独立发生的,因此有 1 2 × 3 × 4 \frac 1{2\times3\times4} 2×3×41 的概率同时出现故障 2 、 3 、 4 2、3、4 234

  约定若相关性矩阵中没有 ‘ x ’ \rm ‘x’ x 记号,则表示该故障原因一定不会产生某故障现象,比如故障原因 A A A,一定不会产生故障现象 1 1 1

  根据历史经验数据,我们统计得到了每一种故障原因出现的概率以及每一种故障原因对应的故障现象产生概率。

  现在已知系统出现的故障现象,求问各个故障原因发生的概率。

【输入格式】

  第 1 1 1 : : 2 2 2 个正整数 N , M N, M N,M N N N 表示故障原因的个数(编号 1 ⋯ N 1 \cdots N 1N), M M M 表示故障现象的个数(编号 1 ⋯ M 1 \cdots M 1M

  第 2 2 2 : : N N N 个整数,第 i i i 个数表示故障原因 i i i 产生的概率 P i P_i Pi.

  第 3 ⋯ N + 2 3 \cdots N + 2 3N+2 : : 每行 M + 1 M + 1 M+1 个整数,第 i + 1 i + 1 i+1 行第 j j j 个整数 P i j P_{i j} Pij 表示故障原因 i i i 出现故障现象 j j j 的概率(百分比) . . .

  第 N + 3 N + 3 N+3 : : 1 1 1 个正整数 K K K,表示目前出现的故障现象数量

  第 N + 4 N + 4 N+4 : : K K K 个正整数,依次为当前出现的故障现象编号,不会重复

【输出格式】

  第 1 ⋯ N 1 \cdots N 1N : : 按概率从高到低输出每种故障原因及其可能的概率,若出现概率相同则优先输出编号小的故障原因。第 1 1 1 个数为故障原因编号,第 2 2 2 个数为故障概率(百分比),保留 2 2 2 位小数。

【样例输入】

3 5
30 20 50
0 50 33 25 0
30 0 35 0 0
0 0 0 25 60
1
3

【样例输出】

2 56.89
1 43.11
3 0.00

【评测用例规模与约定】

  对于所有测试用例, 1 ≤ N ≤ 40 , 1 ≤ M ≤ 20 , 0 ≤ P i ≤ 100 , Σ ( P i ) = 100 , 0 ≤ P i j ≤ 100 1 ≤ N ≤ 40, 1 ≤ M ≤ 20, 0 ≤ P_i ≤ 100,\Sigma(P_i) = 100,0 ≤ P_{i j} ≤ 100 1N40,1M20,0Pi100Σ(Pi)=1000Pij100


贝叶斯定理


#include <stdio.h>
#include <algorithm>
#include <math.h>

int n, m, k, P[40][21];

struct node {
    double p;
    int i;
    inline bool operator<(const node &nd) const {
        return p == nd.p ? i < nd.i : p > nd.p;
    }
} ans[40];

int main() {
	scanf("%d %d", &n, &m);
	for (int i = 0; i < n; ++i)
	    scanf("%d", P[i]), ans[i].i = i + 1;
	for (int i = 0; i < n; ++i)
	    for (int j = 1; j <= m; ++j)
	        scanf("%d", &P[i][j]), P[i][j] = 100 - P[i][j];
	scanf("%d", &k);
	for (int g = 0, j; g < k; ++g) {
	    scanf("%d", &j);
	    for (int i = 0; i < n; ++i)
	        P[i][j] = 100 - P[i][j];
	}
	double tmp = 0;
	for (int i = 0; i < n; ++i) {
	    ans[i].p = *P[i] / 100.0;
	    for (int j = 1; j <= m; ++j)
	        ans[i].p *= P[i][j] / 100.0;
	    tmp += ans[i].p;
	}
	std::sort(ans, ans + n);
	for (int i = 0; i < n; ++i)
	    printf("%d %.2lf\n", ans[i].i, !tmp ? 0.0 : 100 * ans[i].p / tmp);
}

  全概率公式与贝叶斯公式裸题,注意判一下 P ( B ) P(B) P(B) 0 0 0 的情况就行了。

  模板 × 5 \times 5 ×5


试题 H: 机房

时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 256.0 M B 256.0\mathrm{MB} 256.0MB 本题总分: 20 20 20


【问题描述】

  这天,小明在机房学习。

  他发现机房里一共有 n n n 台电脑,编号为 1 1 1 n n n,电脑和电脑之间有网线连接,一共有 n − 1 n−1 n1 根网线将 n n n 台电脑连接起来使得任意两台电脑都直接或者间接地相连。

  小明发现每台电脑转发、发送或者接受信息需要的时间取决于这台电脑和多少台电脑直接相连, 而信息在网线中的传播时间可以忽略。比如如果某台电脑用网线直接连接了另外 d d d 台电脑,那么任何经过这台电脑的信息都会延迟 d d d 单位时间 (发送方和接收方也会产生这样的延迟,当然如果发送方和接收方都是同一台电脑就只会产生一次延迟)。

  小明一共产生了 m m m 个疑问 : : 如果电脑 u i u_i ui 向电脑 v i v_i vi 发送信息,那么信息从 u i u_i ui 传到 v i v_i vi 的最短时间是多少?

【输入格式】

  输入共 n + m n + m n+m 行,第一行为两个正整数 n , m n,m n,m

  后面 n − 1 n−1 n1 行,每行两个正整数 x , y x,y x,y 表示编号为 x x x y y y 的两台电脑用网线直接相连。

  后面 m m m 行,每行两个正整数 u i , v i u_i,v_i ui,vi 表示小明的第 i i i 个疑问。

【输出格式】

  输出共 m m m 行,第 i i i 行一个正整数表示小明第 i i i 个疑问的答案。

【样例输入】

4 3
1 2
1 3
2 4
2 3
3 4
3 3

【样例输出】

5
6
1

【样例说明】

  这四台电脑各自的延迟分别为 2 , 2 , 1 , 1 2,2,1,1 2,2,1,1
  对于第一个询问,从 2 2 2 3 3 3 需要经过 2 , 1 , 3 2,1,3 2,1,3,所以时间和为 2 + 2 + 1 = 5 2 + 2 + 1 = 5 2+2+1=5
  对于第二个询问,从 3 3 3 4 4 4 需要经过 3 , 1 , 2 , 4 3,1,2,4 3,1,2,4,所以时间和为 1 + 2 + 2 + 1 = 6 1+2+2+1 =6 1+2+2+1=6
  对于第三个询问,从 3 3 3 3 3 3 只会产生一次延迟,所以时间为 1 1 1

【评测用例规模与约定】

  对于 30 % 30\% 30% 的数据,保证 n , m ≤ 1000 n,m≤1000 n,m1000
  对于 100 % 100\% 100% 的数据,保证 n , m ≤ 100000 n,m≤100000 n,m100000


Tarjan


#include <stdio.h>

const int N = 100009;

int linked[N], query[N], ans[N];

int next[N << 2], ver[N << 2], idx[N << 2], cur = 0;

int n, m, x, y, fa[N], val[N], parent[N];

bool visited[N];

int find(int rt) { return parent[rt] == rt ? rt : (parent[rt] = find(parent[rt])); }

void tarjan(int u) {
    val[u] += val[fa[u]];
    visited[u] = 1;
    parent[u] = u;
    for (int i = linked[u]; i; i = next[i])
        if (!visited[ver[i]])
            fa[ver[i]] = u, tarjan(ver[i]), parent[ver[i]] = u;
    for (int i = query[u]; i; i = next[i])
        if (visited[ver[i]])
            ans[idx[i]] = val[u] + val[ver[i]] - val[find(ver[i])] - val[fa[find(ver[i])]];
}

int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i < n; ++i) {
        scanf("%d %d", &x, &y);
        ++cur, ++val[x], next[cur] = linked[x], linked[x] = cur, ver[cur] = y;
        ++cur, ++val[y], next[cur] = linked[y], linked[y] = cur, ver[cur] = x;
    }
    for (int i = 0; i < m; ++i) {
        scanf("%d %d", &x, &y);
        ++cur, idx[cur] = i, next[cur] = query[x], query[x] = cur, ver[cur] = y;
        ++cur, idx[cur] = i, next[cur] = query[y], query[y] = cur, ver[cur] = x;
    }
    tarjan(1);
    for (int i = 0; i < m; ++i) printf("%d\n", ans[i]);
}

   L C A \rm LCA LCA 裸题,模板 × 6 \times 6 ×6


试题  I: 齿轮

时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 256.0 M B 256.0\mathrm{MB} 256.0MB 本题总分: 25 25 25


【问题描述】

  这天,小明在组装齿轮。

  他一共有 n n n 个齿轮,第 i i i 个齿轮的半径为 r i r_i ri,他需要把这 n n n 个齿轮按一定顺序从左到右组装起来,这样最左边的齿轮转起来之后,可以传递到最右边的齿轮,并且这些齿轮能够起到提升或者降低转速 (角速度) 的作用。

  小明看着这些齿轮,突然有 Q Q Q 个疑问:能否按一定顺序组装这些齿轮使得最右边的齿轮的转速是最左边的齿轮的 q i q_i qi 倍?

【输入格式】

  输入共 Q + 2 Q + 2 Q+2 行,第一行为两个正整数 n , Q n, Q n,Q,表示齿轮数量和询问数量。

  第二行为 n n n 个正整数 r 1 , r 2 , . . . , r n r_1,r_2, ...,r_n r1,r2,...,rn,表示每个齿轮的半径。

  后面 Q Q Q 行,每行一个正整数 q i q_i qi 表示询问。

【输出格式】

   Q Q Q 行,对于每个询问,如果存在至少一种组装方案满足条件,输出 ‘ Y E S ‘ \rm ‘YES‘ YES,否则输出 ‘ N O ‘ \rm ‘NO‘ NO

【样例输入】

5 3
4 2 3 3 1
2
4
6

【样例输出】

YES
YES
NO

【样例说明】

  询问 1 1 1 方案之一 : : 2   3   3   4   1 2\ 3\ 3\ 4\ 1 2 3 3 4 1
  询问 2 2 2 方案之一 : : 4   2   3   3   1 4\ 2\ 3\ 3\ 1 4 2 3 3 1
  询问 3 3 3 没有方案

【评测用例规模与约定】

  对于 15 % 15\% 15% 的数据,保证 n , Q ≤ 100 n, Q ≤ 100 n,Q100
  对于 30 % 30\% 30% 的数据,保证 n , Q ≤ 2000 n, Q ≤ 2000 n,Q2000
  对于 100 % 100\% 100% 的数据,保证 n , Q ≤ 2 × 1 0 5 ; a i , q i ≤ 2 × 1 0 5 n, Q ≤ 2 × 10^5; a_i, q_i ≤ 2 × 10^5 n,Q2×105;ai,qi2×105


  容易发现 n n n 个齿轮按一定顺序组装起来,最左齿轮与最右齿轮之间,转速的关系与这一序列齿轮中间 2 ∼ n − 1 2 \sim n-1 2n1 个无关。

  于是问题就被转变为,对于每一个 q q q,是否存在一对 i , j i,j i,j,满足 r i = q r j r_i = qr_j ri=qrj,看一眼数据范围,直接倍数法离线求解了。

#include <stdio.h>

const int N = 200000;

bool g[N + 1], q[N + 1];

int n, r, Q;

int main() {
    scanf("%d %d", &n, &Q);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &r);
        if (g[r]) q[1] = 1;
        g[r] = 1;
    }
    for (int i = 1; i <= N; ++i)
        if (g[i])
            for (int j = 2; i * j <= N; ++j)
                if (g[i * j]) q[j] = 1;
    for (int i = 0; i < Q; ++i)
        scanf("%d", &r), puts(q[r] ? "YES" : "NO");
}

试题 J: 搬砖

时间限制: 1.0 s 1.0\mathrm s 1.0s 内存限制: 256.0 M B 256.0\mathrm{MB} 256.0MB 本题总分: 25 25 25


【问题描述】

  这天,小明在搬砖。

  他一共有 n n n 块砖,他发现第 i i i 砖的重量为 w i w_i wi,价值为 v i v_i vi。他突然想从这些砖中选一些出来从下到上堆成一座塔,并且对于塔中的每一块砖来说,它上面所有砖的重量和不能超过它自身的价值。

  他想知道这样堆成的塔的总价值(即塔中所有砖块的价值和)最大是多少。

【输入格式】

  输入共 n + 1 n + 1 n+1 行,第一行为一个正整数 n n n,表示砖块的数量。

  后面 n n n 行,每行两个正整数 w i , v i w_i, v_i wi,vi 分别表示每块砖的重量和价值。

【输出格式】

  一行,一个整数表示答案。

【样例输入】

5
4 4
1 1
5 2
5 5
4 3

【样例输出】

10

【样例说明】

  选择第 1 、 2 、 4 1、2、4 124 块砖,从上到下按照 2 、 1 、 4 2、1、4 214 的顺序堆成一座塔,总价值为 4 + 1 + 5 = 10 4 + 1 + 5 = 10 4+1+5=10

【评测用例规模与约定】

  对于 20 % 20\% 20% 的数据,保证 n ≤ 10 n ≤ 10 n10
  对于 100 % 100\% 100% 的数据,保证 n ≤ 1000 ; w i ≤ 20 ; v i ≤ 20000 n ≤ 1000; w_i ≤ 20; v_i ≤ 20000 n1000;wi20;vi20000


背包 DP


#include <stdio.h>
#include <algorithm>
#include <utility>

inline int max(int a, int b) { return a > b ? a : b; }

std::pair<int, int> brick[20000];

int n, dp[200001];

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
        scanf("%d %d", &brick[i].second, &brick[i].first);
    std::sort(brick, brick + n);
    for (int i = 0; i < n; ++i)
        for (int j = brick[i].first; j >= 0; --j)
            if (dp[j] || !j) dp[j + brick[i].second] = max(dp[j + brick[i].second], dp[j] + brick[i].first);
    for (int i = brick[n - 1].first + brick[n - 1].second; i >= 0; --i)
        if (dp[i]) {
            printf("%d", dp[i]);
            return 0;
        }
}

有关第十三届蓝桥杯大赛软件赛决赛(C/C++ 大学B组)的更多相关文章

  1. 软件测试基础 - 2

    Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功

  2. 网站日志分析软件--让网站日志分析工作变得更简单 - 2

    网站的日志分析,是seo优化不可忽视的一门功课,但网站越大,每天产生的日志就越大,大站一天都可以产生几个G的网站日志,如果光靠肉眼去分析,那可能看到猴年马月都看不完,因此借助网站日志分析工具去分析网站日志,那将会使网站日志分析工作变得更简单。下面推荐两款网站日志分析软件。第一款:逆火网站日志分析器逆火网站日志分析器是一款功能全面的网站服务器日志分析软件。通过分析网站的日志文件,不仅能够精准的知道网站的访问量、网站的访问来源,网站的广告点击,访客的地区统计,搜索引擎关键字查询等,还能够一次性分析多个网站的日志文件,让你轻松管理网站。逆火网站日志分析器下载地址:https://pan.baidu.

  3. 蓝桥杯备赛(二) - 2

    目录前言: 一、ASC分析代码实现二、 卡片分析代码实现三、 直线分析代码实现四、货物摆放分析代码实现小结:前言:  在刷题的过程中,发现蓝桥杯的题目和力扣的差别很大。让人有一种不一样的感觉,蓝桥杯题目偏向对于实际问题用编程去的解决,而力扣给人感觉很锻炼自己的编程思维,逻辑能力。两者结合去刷,相信会有不一样的收获。 一、ASC  已知大写字母A的ASCII码为65,请问大写字母L的ASCII码是多少?分析  这道题目看上去很简单,我们需确定自己计算的准确,所以我建议用编程去解决。代码实现publicclassTest8{publicstaticvoidmain(String[]args){Sy

  4. 【血泪建议】软件测试岗位现状,可惜之前没人告诉我,肠子都晦青了.... - 2

    谈到现状,国内的软件测试行情目前呈现了两极分化的极端情况。一个是早期的手工测试人员吐槽工作不好做,即使有工作也是外包,而且薪资太低;一方面是很多互联网企业感叹自动化测试人才难找,有技术的自动化测试工程师,高薪难聘。这两者其实并不矛盾。手工测试工作难找也确实是目前真实的行情早期从事功能测试的手工测试人员,在测试方面大多采用手动、人工执行的方式查找软件缺陷和BUG,用行业术语来描述就是“点点点”。这种测试方式耗费大量人力和资源,工作效率却十分低下。在早期软件复杂和迭代程度不高的情况下,有资本的企业会“供养”一批这样的手工测试人员。但对测试员本身来讲,毫无技术难度的工作,和几乎没有保障的薪资水平,直

  5. 蓝桥杯C/C++VIP试题每日一练之报时助手 - 2

    ?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是:  如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。  如果m不为0,则将时读出来,然后将分读出来,如5

  6. 0基础学习软件测试有哪些建议 - 2

    其实现在基础的资料和视频到处都是,就是看你有没有认真的去找学习资源了,去哪里学习都是要看你个人靠谱不靠谱,再好的教程和老师,你自己学习不进去也是白搭在正式选择之前,大可以在各种学习网站里面找找学习资源先自己学习一下为什么选择学软件测试?同学们理由众多!大概分这几类:①不受开发语言、行业产品变化限制;②入门更简单,对零基础、女生都友好;③软件项目都需要测试人员,职业生涯稳;④学习周期短,但薪资并不低。要想“肩扛”一条线?需掌握三大技能:技能1:掌握测试流程,熟悉系统框架能提前与开发人员一起制定测试计划,通过测试左移,推动代码评审,代码审计,单元测试,自动化冒烟测试,来保证研发阶段的质量。技能2:

  7. “网安三人行”盘点:软件供应链安全的那些事儿 - 2

    2022年伊始,默安科技联合数世咨询举办以“软件供应链安全的时与势”为主题的访谈活动,由数世咨询创始人李少鹏主持,邀请贝壳安全研发负责人李文鹏、北京邮电大学副教授张文博、默安科技副总裁沈锡镛三位行业大咖做客网安小酒馆,从产业、企业、学术的不同维度,共同探讨软件供应链安全建设的新思路,为业界呈现了一场开年网安盛宴。随着全球软件供应链安全事件频发,软件供应链安全逐渐成为业界关注焦点,也成为影响国家重要信息系统安全与关键信息基础设施安全的重要因素,以及网络安全保障体系和能力建设的重要环节。嘉宾们围绕软件供应链安全发展的主要驱动力、关基行业中的实施现状和落地难点、产学研成果转化、软件供应链安全的重要性

  8. 十四届蓝桥青少组模拟赛Python-20221108 - 2

    十四届蓝桥青少组模拟赛Python-20221108T1.二进制位数十进制整数2在十进制中是1位数,在二进制中对应10,是2位数。十进制整数22在十进制中是2位数,在二进制中对应10110,是5位数。请问十进制整数2022在二进制中是几位数?print(len(bin(2022))-2)#运行结果:11T2.晨跑小蓝每周六、周日都晨跑,每月的1、11、21、31日也晨跑。其它时间不晨跑。已知2022年1月1日是周六,请问小蓝整个2022年晨跑多少天?#样例代码1ls=[0,31,28,31,30,31,30,31,31,30,31,30,31]ans=0k=6foriinrange(1,13)

  9. 蓝桥杯 stm32 MCP4017 - 2

    本文代码使用HAL库。文章目录前言一、MCP4017的重要特性二、MCP4017计算RBW阻值三、MCP4017地址四、MCP4017读写函数五、CubeMX创建工程(利用ADC测量MCP4017电压)、对应代码:总结前言一、MCP4017的重要特性蓝桥杯板子上的是MCP4017T-104ELT,如图1。MCP4017是一个可编程电阻,通过写入的数值可以改变电阻的大小。重点在于6引脚(W),5引脚(B&#

  10. [蓝桥杯单片机]学习笔记——串口通信的基本原理与应用 - 2

    目录一、原理部分1、什么是串行通信(1)并行通信与串行通信(2)串行通信的制式(3)串行通信的主要方式  2、配置串口(1)SCON和PCON:串行口1的控制寄存器(2)SBUF:串行口数据缓冲寄存器 (3)AUXR:辅助寄存器​编辑(4)ES、PS:与串行口1中断相关的寄存器(5)波特率设置  3、串口框架编写二、程序案例一、原理部分1、什么是串行通信(1)并行通信与串行通信微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。并行通信:数据的各位同时发送与接收,每个数据位使用一条导线,这种方式传输快,但是需要多条导线进行信号传输。串行通信:数据一位一

随机推荐