第十二届蓝桥杯 2021年省赛真题 (C/C++ 大学A组) 第一场_路径 蓝桥杯 2021-程序员宅基地

技术标签: 蓝桥杯  c/c++  


解析移步对应 Java组 的题解


#A 卡片

本题总分: 5 5 5


问题描述

  小蓝有很多数字卡片,每张卡片上都是数字 0 0 0 9 9 9
  小蓝准备用这些卡片来拼一些数,他想从 1 1 1 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。
  小蓝想知道自己能从 1 1 1 拼到多少。
  例如,当小蓝有 30 30 30 张卡片,其中 0 0 0 9 9 9 3 3 3 张,则小蓝可以拼出 1 1 1 10 10 10,但是拼 11 11 11 时卡片 1 1 1 已经只有一张了,不够拼出 11 11 11
  现在小蓝手里有 0 0 0 9 9 9 的卡片各 2021 2021 2021 张,共 20210 20210 20210 张,请问小蓝可以从 1 1 1 拼到多少?
  提示:建议使用计算机编程解决问题。


答案提交

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


3181


calcCode:

#include <stdio.h>

int n, ans, cnt;

int main() {
    
    while (1) {
    
       n = ans;
       while (n) {
    
           if (n % 10 == 1) cnt++;
           n /= 10;
       }
       if (cnt < 2021) ans++;
       else break;
    }
    printf("%d", ans);
}

#B 直线

本题总分: 5 5 5


问题描述

  在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。
  给定平面上 2 × 3 2 × 3 2×3 个整点 { ( x , y ) ∣ 0 ≤ x < 2 , 0 ≤ y < 3 , x ∈ Z , y ∈ Z } \{(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z\} { (x,y)0x<2,0y<3,xZ,yZ},即横坐标是 0 0 0 1 1 1 (包含 0 0 0 1 1 1) 之间的整数、纵坐标是 0 0 0 2 2 2 (包含 0 0 0 2 2 2) 之间的整数的点。这些点一共确定了 11 11 11 条不同的直线。
  给定平面上 20 × 21 20 × 21 20×21 个整点 { ( x , y ) ∣ 0 ≤ x < 20 , 0 ≤ y < 21 , x ∈ Z , y ∈ Z } \{(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z\} { (x,y)0x<20,0y<21,xZ,yZ},即横坐标是 0 0 0 19 19 19 (包含 0 0 0 19 19 19) 之间的整数、纵坐标是 0 0 0 20 20 20 (包含 0 0 0 20 20 20) 之间的整数的点。请问这些点一共确定了多少条不同的直线。


答案提交

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


40257


calcCode:

#include <stdio.h>

const int X = 20, Y = 21;

int linked[X][Y][X][Y], ans;

int main() {
    
    for (int x1 = 0; x1 < X; x1++)
        for (int y1 = 0; y1 < Y; ++y1) {
    
            linked[x1][y1][x1][y1] = 1;
            for (int x2 = 0; x2 < X; ++x2)
                for (int y2 = 0; y2 < Y; ++y2)
                    if (!linked[x1][y1][x2][y2]) {
    
                        int x = x1, x_offset = x1 - x2;
                        int y = y1, y_offset = y1 - y2;
                        while (x >= 0 && x < X && y >= 0 && y < Y) x -= x_offset, y -= y_offset;
                        for (x += x_offset, y += y_offset; x >= 0 && x < X && y >= 0 && y < Y; x += x_offset, y += y_offset)
                            for (int xx = x, yy = y; xx >= 0 && xx < X && yy >= 0 && yy < Y; xx += x_offset, yy += y_offset)
                                linked[x][y][xx][yy] = linked[xx][yy][x][y] = 1;
                        ans++;
                    }
        }
    printf("%d", ans);
}

#C 货物摆放

本题总分: 10 10 10


问题描述

  小蓝有一个超大的仓库,可以摆放很多货物。
  现在,小蓝有 n n n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。
  小蓝希望所有的货物最终摆成一个大的立方体。即在长、宽、高的方向上分别堆 L 、 W 、 H L、W、H LWH 的货物,满足 n = L × W × H n = L × W × H n=L×W×H
  给定 n n n,请问有多少种堆放货物的方案满足要求。
  例如,当 n = 4 n = 4 n=4 时,有以下 6 6 6 种方案: 1 × 1 × 4 1×1×4 1×1×4 1 × 2 × 2 1×2×2 1×2×2 1 × 4 × 1 1×4×1 1×4×1 2 × 1 × 2 2×1×2 2×1×2 2 × 2 × 1 2 × 2 × 1 2×2×1 4 × 1 × 1 4 × 1 × 1 4×1×1
  请问,当 n = 2021041820210418 n = 2021041820210418 n=2021041820210418 (注意有 16 16 16 位数字)时,总共有多少种方案?
  提示:建议使用计算机编程解决问题。


答案提交

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


2430


calcCode:

#include <bits/stdc++.h>

typedef long long ll;

using namespace std;

ll N = 2021041820210418, n = 1, ans;

int main() {
    
    priority_queue<int> exps;
    for (int i = 2; i <= sqrt(N); i++)
        if (N % i == 0) {
    
            int exp = 0;
            while (N % i == 0)
                N /= i, exp++;
            exps.push(exp);
        }
    if (N != 1) exps.push(1);
    for (int i = 2; exps.size(); i++) {
    
        bool flag = 1;
        for (int a = 2; a < i; ++a)
            if (i % a == 0) flag = 0;
        if (flag) n *= pow(i, exps.top()), exps.pop();
    }
    for (ll i = 1; i <= n; i++)
        for (ll j = 1; j <= n; j++)
            if (n % (i * j) == 0) ans++;
    cout << ans << endl;
}

#D 路径

本题总分: 10 10 10


问题描述

  小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。
  小蓝的图由 2021 2021 2021 个结点组成,依次编号 1 1 1 2021 2021 2021。对于两个不同的结点 a , b a, b a,b,如果 a a a b b b 的差的绝对值大于 21 21 21,则两个结点之间没有边相连;如果 a a a b b b 的差的绝对值小于等于 21 21 21,则两个点之间有一条长度为 a a a b b b 的最小公倍数的无向边相连。
  例如:结点 1 1 1 和结点 23 23 23 之间没有边相连;结点 3 3 3 和结点 24 24 24 之间有一条无向边,长度为 24 24 24;结点 15 15 15 和结点 25 25 25 之间有一条无向边,长度为 75 75 75
  请计算,结点 1 1 1 和结点 2021 2021 2021 之间的最短路径长度是多少。
  提示:建议使用计算机编程解决问题。


答案提交

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


10266837


calcCode:

#include <stdio.h>
#include <string.h>

const int N = 2021;
int map[N + 1][N + 1];

int gcd(int a, int b) {
     return b ? gcd(b, a % b) : a; }

int lcm(int a, int b) {
     return a * b / gcd(a, b); }

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

int main() {
    
    memset(&map, 0x3F, sizeof map);
    for (int u = 1; u <= N; u++)
        for (int v = min(N, u + 21); v > u; --v)
            map[u][v] = map[v][u] = lcm(u, v);
    for (int k = 1; k <= N; k++)
        for (int i = 1; i <= N; i++)
            for (int j = 1; j <= N; j++)
                map[i][j] = min(map[i][j], map[i][k] + map[k][j]);
    printf("%d", map[1][N]);
}

#E 回路计数

本题总分: 15 15 15


问题描述

  蓝桥学院由 21 21 21 栋教学楼组成,教学楼编号 1 1 1 21 21 21。对于两栋教学楼 a a a b b b,当 a a a b b b 互质时, a a a b b b 之间有一条走廊直接相连,两个方向皆可通行,否则没有直接连接的走廊。
  小蓝现在在第一栋教学楼,他想要访问每栋教学楼正好一次,最终回到第一栋教学楼(即走一条哈密尔顿回路),请问他有多少种不同的访问方案?两个访问方案不同是指存在某个 i i i,小蓝在两个访问方法中访问完教学楼 i i i 后访问了不同的教学楼。
  提示:建议使用计算机编程解决问题。


答案提交

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


881012367360


calcCode:

#include <bits/stdc++.h>

typedef long long ll;

using namespace std;

const int N = 21;

ll cnt[N - 1][1 << N - 1];

vector<int> graph[N];

ll dfs(int start, int status) {
    
    if (status == 0) return 1;
    if (cnt[start][status] >= 0) return cnt[start][status];
    ll sum = 0;
    for (int v : graph[start])
        if (status & (1 << v))
            sum += dfs(v, status - (1 << v));
    return cnt[start][status] = sum;
}

int gcd(int a, int b) {
     return b? gcd(b, a % b) : a; }

int main() {
    
    for (int i = 2; i <= N; i++)
        for (int j = 2; j < i; j++)
            if (gcd(i, j) == 1)
                graph[i - 2].push_back(j - 2),
                graph[j - 2].push_back(i - 2);
    memset(cnt, 0xC3, sizeof cnt);
    ll sum = 0;
    for (int i = 0; i < N - 1; i++)
        sum += dfs(i, (1 << N - 1) - (1 << i) - 1);
    cout << sum << endl;
}

#F 砝码称重

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


问题描述

  你有一架天平和 N N N 个砝码,这 N N N 个砝码重量依次是 W 1 , W 2 , ⋅ ⋅ ⋅ , W N W_1, W_2, · · · , W_N W1,W2,,WN
  请你计算一共可以称出多少种不同的重量?
  注意砝码可以放在天平两边。


输入格式

  输入的第一行包含一个整数 N N N
  第二行包含 N N N 个整数: W 1 , W 2 , W 3 , ⋯   , W N W_1, W_2, W_3, \cdots , W_N W1,W2,W3,,WN


输出格式

  输出一个整数代表答案。


测试样例1

Input:
3
1 4 6

Output:
10

Explanation:
能称出的 10 种重量是:1、2、3、4、5、6、7、9、10、11。
1 = 1;
2 = 6 − 4 (天平一边放 6,另一边放 4);
3 = 4 − 1;
4 = 4;
5 = 6 − 1;
6 = 6;
7 = 1 + 6;
9 = 4 + 6 − 1;
10 = 4 + 6;
11 = 1 + 4 + 6。

评测用例规模与约定

  对于 50 50 50% 的评测用例, 1 ≤ N ≤ 15 1 ≤ N ≤ 15 1N15
  对于所有评测用例, 1 ≤ N ≤ 100 1 ≤ N ≤ 100 1N100 N N N 个砝码总重不超过 100000 100000 100000


背包 DP


  终于逮到一个 J a v a \mathrm{Java} Java 组没有的题,可惜是 F \mathrm F F 题,还是个简单背包。

  不过依题意若干砝码做加减运算,得到的绝对值可以视为一个可以称出的重量,

  如果我们将若干砝码可能加减出的结果放在数轴上,显然可以发现,它是以原点对称的,于是我们可以只对正整数部分做背包,然后将上一轮背包 ( 1 , w i ) (1,w_i) (1,wi) 部分的结果视为 ( − w i , − 1 ) (-w_i, -1) (wi,1),可以减少算法的常数。

#include <bits/stdc++.h>

using namespace std;

const int N = 100000;

bool dp[N + 1 << 1] = {
    1}, bf[N + 1 << 1] = {
    1};

int n, w, ans;

int main() {
    
    cin >> n;
    while (n--) {
    
        cin >> w;
        swap(dp, bf);
        for (int i = N; i >= w; i--) dp[i] = bf[i] | bf[i - w] | bf[i + w];
        for (int i = 1; i < w; i++) dp[i] |= bf[w - i];
    }
    for (int i = 1; i <= N; i++) if (dp[i]) ans++;
    cout << ans << endl;
}

#G 异或数列

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


   A l i c e \mathrm{Alice} Alice B o b \mathrm{Bob} Bob 正在玩一个异或数列的游戏。初始时, A l i c e \mathrm{Alice} Alice B o b \mathrm{Bob} Bob 分别有一个整数 a a a b b b,有一个给定的长度为 n n n 的公共数列 X 1 , X 2 , ⋯   , X n X_1, X_2, \cdots , X_n X1,X2,,Xn
   A l i c e \mathrm{Alice} Alice B o b \mathrm{Bob} Bob 轮流操作, A l i c e \mathrm{Alice} Alice 先手,每步可以在以下两种选项中选一种:
  选项 1 1 1:从数列中选一个 X i X_i Xi A l i c e \mathrm{Alice} Alice 的数异或上,或者说令 a a a 变为 a ⊕ X i a ⊕ X_i aXi。(其中 ⊕ ⊕ 表示按位异或)
  选项 2 2 2:从数列中选一个 X i X_i Xi B o b \mathrm{Bob} Bob 的数异或上,或者说令 b b b 变为 b ⊕ X i b ⊕ X_i bXi
  每个数 X i X_i Xi 都只能用一次,当所有 X i X_i Xi 均被使用后( n n n 轮后)游戏结束。游戏结束时,拥有的数比较大的一方获胜,如果双方数值相同,即为平手。
  现在双方都足够聪明,都采用最优策略,请问谁能获胜?


输入格式

  每个评测用例包含多组询问。询问之间彼此独立。
  输入的第一行包含一个整数 T T T,表示询问数。
  接下来 T T T 行每行包含一组询问。其中第 i i i 行的第一个整数 n i n_i ni 表示数列长度,随后 n i n_i ni 个整数 X 1 , X 2 , ⋯   , X n i X_1, X_2, \cdots , X_{ni} X1,X2,,Xni 表示数列中的每个数。


输出格式

  输出 T T T 行,依次对应每组询问的答案。
  每行包含一个整数 1 1 1 0 0 0 − 1 −1 1 分别表示 A l i c e \mathrm{Alice} Alice 胜、平局或败。


测试样例1

Input:
4
1 1
1 0
2 2 1
7 992438 1006399 781139 985280 4729 872779 563580

Output:
1
0
1
1

评测用例规模与约定

  对于所有评测用例, 1 ≤ T ≤ 200000 1 \leq T \leq 200000 1T200000 1 ≤ ∑ i = 1 T n i ≤ 200000 1 \leq \sum_{i=1}^T n_i \leq 200000 1i=1Tni200000 0 ≤ X i < 2 20 0 \leq X_i < 2^{20} 0Xi<220


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

int T, S, n, A[200010];

int main() {
    
    scanf("%d", &T);
    while (T--) {
    
        S = 0;
        scanf("%d", &n);
        for (int i = 0; i < n; ++i)
        	scanf("%d", &A[i]), S ^= A[i];
        if (S) {
    
            int k = log2(S), a = 0;
            for (int i = 0; i < n; ++i) if (A[i] >> k & 1) ++a;
            if (n & 1 || a == 1) printf("1\n");
            else printf("-1\n");
        } else printf("0\n");
    }
}

#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 编号,其中 1 1 1 号结点是根,每个结点的父结点的编号比自己的编号小。请你计算其通过 “左孩子右兄弟” 表示法转化成的二叉树,高度最高是多少。注:只有根结点这一个结点的树高度为 0 0 0
  例如如下的多叉树:
请添加图片描述
  可能有以下 3 3 3 种 (这里只列出 3 3 3 种,并不是全部) 不同的 “左孩子右兄弟”表示:
请添加图片描述
  其中最后一种高度最高,为 4 4 4


输入格式

  输入的第一行包含一个整数 N N N
  以下 N − 1 N −1 N1 行,每行包含一个整数,依次表示 2 2 2 N N N 号结点的父结点编号。


输出格式

  输出一个整数表示答案。


测试样例1

Input:
5
1
1
1
2

Output:
4

评测用例规模与约定

  对于 30 30 30% 的评测用例, 1 ≤ N ≤ 20 1 ≤ N ≤ 20 1N20
  对于所有评测用例, 1 ≤ N ≤ 100000 1 ≤ N ≤ 100000 1N100000


#include <bits/stdc++.h>

using namespace std;

#define N 100005

vector<int> tree[N];

int dp(int root) {
    
    if (!tree[root].size()) return 0;
    int res = 0;
    for (int son : tree[root])
        res = max(res, dp(son));
    return res + tree[root].size();
}

int main() {
    
    int n, t;
    cin >> n;
    for (int i = 2; i <= n; ++i)
        cin >> t, tree[t].push_back(i);
    cout << dp(1) << endl;
}

#I 括号序列

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


问题描述

  给定一个括号序列,要求尽可能少地添加若干括号使得括号序列变得合法,当添加完成后,会产生不同的添加结果,请问有多少种本质不同的添加结果。
  两个结果是本质不同的是指存在某个位置一个结果是左括号,而另一个是右括号。
  例如,对于括号序列 (((),只需要添加两个括号就能让其合法,有以下几种不同的添加结果:()()()、()(())、(())()、(()()) 和 ((()))。


输入格式

  输入一行包含一个字符串 s s s,表示给定的括号序列,序列中只有左括号和右括号。


输出格式

  输出一个整数表示答案,答案可能很大,请输出答案除以 1000000007 1000000007 1000000007 (即 1 0 9 + 7 10^{9} + 7 109+7) 的余数。


测试样例1

Input:
((()

Output:
5

评测用例规模与约定

  对于 40 40 40% 的评测用例, ∣ s ∣ ≤ 200 |s| ≤ 200 s200
  对于所有评测用例, 1 ≤ ∣ s ∣ ≤ 5000 1 ≤ |s| ≤ 5000 1s5000


#include <stdio.h>
#include <string.h>

typedef long long ll;

#define N 5555

int dp[N][N], p = 1000000007;

char str[N] = {
    '$'};

int calc(char *str) {
    
    memset(dp, 0, sizeof dp);
    dp[0][0] = 1;
    int opening = 0, n = strlen(str) - 1;
    for (int i = 1; i <= n; i++) {
    
        if (str[i] == '(') {
    
            for (int j = 1; j <= n; j++)
                dp[i][j] = dp[i - 1][j - 1];
            opening++;
        }
        else {
    
            dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) % p;
            for (int j = 1; j <= n; j++)
                dp[i][j] = (dp[i][j - 1] + dp[i - 1][j + 1]) % p;
            if (opening) opening--;
        }
    }
    return dp[n][opening];
}

int reverse(char *str) {
    
    for (int i = 1, j = strlen(str) - 1; i <= j; i++, j--) {
    
        char temp = str[i] ^ 1;
        str[i] = str[j] ^ 1;
        str[j] = temp;
    }
}

int main() {
    
    scanf("%s", str + 1);
    ll ans = calc(str);
    reverse(str);
    printf("%d\n", ans * calc(str) % p);
}

#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 包糖果分给 m m m 个小朋友。每包糖果都要分出去,每个小朋友至少要分一包,也可以分多包。
  小蓝已经提前将糖果准备好了,为了在宴会当天能把糖果分得更平均一些,小蓝要先计算好分配方案。
  小蓝将糖果从 1 1 1 n n n 编号,第 i i i 包糖果重 w i w_i wi。小朋友从 1 1 1 m m m 编号。每个小朋友只能分到编号连续的糖果。小蓝想了很久没想出合适的分配方案使得每个小朋友分到的糖果差不多重。因此需要你帮他一起想办法。为了更好的分配糖果,他可以再买一些糖果,让某一些编号的糖果有两份。当某个编号的糖果有两份时,一个小朋友最多只能分其中的一份。
  请找一个方案,使得小朋友分到的糖果的最大重量和最小重量的差最小,请输出这个差。
  例如,小蓝现在有 5 5 5 包糖果,重量分别为 6 , 1 , 2 , 7 , 9 6, 1, 2, 7, 9 6,1,2,7,9,如果小蓝要分给两个小朋友,则他可以将所有糖果再买一份,两个小朋友都分到 1 1 1 5 5 5 包糖果,重量都是 25 25 25,差为 0 0 0
  再如,小蓝现在有 5 5 5 包糖果,重量分别为 6 , 1 , 2 , 7 , 9 6, 1, 2, 7, 9 6,1,2,7,9,如果小蓝要分给三个小朋友,则他可以将第 3 3 3 包糖果再买一份,第一个小朋友分 1 1 1 3 3 3 包,第二个小朋友分 3 3 3 4 4 4 包,第三个小朋友分第 5 5 5 包,每个小朋友分到的重量都是 9 9 9,差为 0 0 0
  再如,小蓝现在有 5 5 5 包糖果,重量分别为 6 , 1 , 2 , 7 , 9 6, 1, 2, 7, 9 6,1,2,7,9,如果小蓝要分给四个小朋友,则他可以将第 3 3 3 包和第 5 5 5 包糖果再买一份,仍然可以每个小朋友分到的重量都是 9 9 9,差为 0 0 0
  再如,小蓝现在有 5 5 5 包糖果,重量分别为 6 , 1 , 2 , 7 , 9 6, 1, 2, 7, 9 6,1,2,7,9,如果小蓝要分给五个小朋友,则他可以将第 4 4 4 包和第 5 5 5 包糖果再买一份,第一个小朋友分第 1 1 1 2 2 2 包重量为 7 7 7,第二个小朋友分第 3 3 3 4 4 4 包重量为 9 9 9,第三个小朋友分第 4 4 4 包重量为 7 7 7,第四个和第五个小朋友都分第 5 5 5 包重量为 9 9 9。差为 2 2 2


输入格式

  输入第一行包含两个整数 n n n m m m,分别表示糖果包数和小朋友数量。
  第二行包含 n n n 个整数 w 1 , w 2 , ⋅ ⋅ ⋅ , w n w_1, w_2, · · · , w_n w1,w2,,wn,表示每包糖果的重量。


输出格式

  输出一个整数,表示在最优情况下小朋友分到的糖果的最大重量和最小重量的差。


测试样例1

Input:
5 2
6 1 2 7 9

Output:
0

测试样例2

Input:
5 5
6 1 2 7 9

Output:
2

评测用例规模与约定

  对于 30 30 30% 的评测用例, 1 ≤ n ≤ 10 1 \leq n \leq 10 1n10 1 ≤ m ≤ 10 1 \leq m \leq 10 1m10 1 ≤ w i ≤ 10 1 \leq w_i \leq 10 1wi10
  对于 60 60 60% 的评测用例, 1 ≤ n ≤ 30 1 \leq n \leq 30 1n30 1 ≤ m ≤ 20 1 \leq m \leq 20 1m20 1 ≤ w i ≤ 30 1 \leq w_i \leq 30 1wi30
  对于所有评测用例, 1 ≤ n ≤ 100 1 \leq n \leq 100 1n100 1 ≤ m ≤ 50 1 \leq m \leq 50 1m50 1 ≤ w i ≤ 100 1 \leq w_i \leq 100 1wi100。在评测数据中, w i w_i wi 随机生成,在某个区间均匀分布。


#include <stdio.h>
#include <string.h>

int dp[51][101][101], W[101], n, m, ans = 0x3F3F3F3F;

int max(int arg1, int arg2) {
     return arg1 > arg2 ? arg1 : arg2; }

int min(int arg1, int arg2) {
     return arg1 < arg2 ? arg1 : arg2; }

int main() {
    
    memset(dp, 0x3F, sizeof dp);
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d", &W[i]), W[i] += W[i - 1];
    dp[0][0][0] = 0;
    for (int minW = W[n] * 2 / m; minW > 0; minW--) {
    
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++) {
    
                int trans2 = 0, trans3 = 0;
                for (int k = 1; k <= j; k++) {
    
                    dp[i][j][k] = dp[i][j][k - 1];
                    while (trans2 < k && W[j] - W[trans2 + 1] >= minW &&
                    	max(dp[i - 1][trans2 + 1][trans2 + 1], W[j] - W[trans2 + 1]) <= max(dp[i - 1][trans2][trans2], W[j] - W[trans2])) trans2++;
                    if (W[j] - W[trans2] >= minW)
                        dp[i][j][k] = min(dp[i][j][k], max(dp[i - 1][trans2][trans2], W[j] - W[trans2]));
                    while (trans3 < k && W[j] - W[trans3 + 1] >= minW &&
                        max(dp[i - 1][k][trans3 + 1], W[j] - W[trans3 + 1]) <= max(dp[i - 1][k][trans3 + 1], W[j] - W[trans3])) trans3++;
                    if (W[j] - W[trans3] >= minW)
                        dp[i][j][k] = min(dp[i][j][k], max(dp[i - 1][k][trans3], W[j] - W[trans3]));
                }
            }
        ans = min(ans, dp[m][n][n] - minW);
    }
    printf("%d\n", ans);
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_43449564/article/details/123446194

智能推荐

数据库语法复习

数据库语法通常指的是用于管理和操作数据库的各种命令和语句。这些语法因不同的数据库管理系统(DBMS)而异,但大多数关系型数据库管理系统(RDBMS)都支持SQL(结构化查询语言)作为其核心语言。

OSQP文档学习-程序员宅基地

文章浏览阅读1.3k次,点赞27次,收藏22次。osqp求解器官方文档学习_osqp

开源语音格式speex教程(for iOS)_speex的encode方法-程序员宅基地

文章浏览阅读997次。转自http://www.cocoachina.com/bbs/read.php?tid=114755&keyword=speex最新的编译博客最新的Demo这两天在折腾语音的东西,实现类似微信上对讲机的功能,做了两个Demo,一种使用lib-amr库用amr格式实现的,这个网上有现成的教程,所以还是比较好实现的。另一个是用的speex库,这个提的人很多,但是出教程的不_speex的encode方法

STM32+ESP01S(WIFI)上传温湿度(DHT11)至巴法云+手机app_stm32智能加湿器wifi控制app-程序员宅基地

文章浏览阅读1.5k次,点赞26次,收藏35次。翻东西时发现一个ESP01S模块,想着玩一下本篇学习ESP01S连接巴法云STM32F103C8T6最小系统板ESP01S模块DHT11温湿度传感器本篇为学习总结,只为学习测试基础功能,没有进行太多测试,可能隐藏一些暂未发现的问题,欢迎大佬们指正。_stm32智能加湿器wifi控制app

使用Gabor滤波器进行指纹增强:Matlab源代码详解_指纹gabor增强源码-程序员宅基地

文章浏览阅读228次。接着,我们可以使用wiener2函数进行噪声去除操作,以便更好的进行后续的指纹增强。但是,由于受到外部环境的影响和指纹本身特性的限制,指纹图像往往出现模糊、噪声等问题,使得指纹识别的准确率大大降低。其中,lambda表示滤波器的波长,theta表示滤波器的方向,psi表示滤波器的相位偏移,gamma表示滤波器的宽度,bw表示滤波器的带宽,N表示滤波器的个数。通过以上步骤,我们可以使用Gabor滤波器对指纹图像进行增强,得到更加清晰的指纹图像,提高指纹识别的准确率。_指纹gabor增强源码

(五)Docker 安装 redis镜像+启动redis容器(超详细)-程序员宅基地

文章浏览阅读7.7k次,点赞4次,收藏19次。(五)Docker 安装 redis镜像+启动redis容器(4)、命令参数含义:容器=完整Linuxdocker run:在docker中启动一个容器实例-p 6379:6379:指定宿主机端口与容器端口映射关系,容器与主机映射端口为,主机6379,容器6379,访问Linux端口就能访问到MySQL容器--name redis:容器运行后的名称,创建的容器名称。_redis镜像

随便推点

前端发版缓存问题

前端发版缓存问题

探索潜力:中心化交易所平台币的对比分析

相比之下,市值较低的平台币,如BMX、BGB和MX,具有更大的增长潜力,呈现出更多的增长机会。在过去的一年里,受益于美国股市上比特币 ETF 的上市和比特币供应量的第四次减半,比特币的价格一度飙升至73,000美元以上,达到历史新高。本文旨在为读者提供对这七种选定平台币的全面分析,评估它们的价值和潜力,并研究价格和市值增长指标、回购机制、功能权益以及其发行方的市场表现。随着越来越多的开发者和项目选择在这些区块链上构建应用程序,这些区块链的持续发展有助于提升其原生代币的可用性和需求,从而扩展其使用场景。

C语言:项目实践(贪吃蛇)

相信大家都玩过贪吃蛇这款游戏吧,贪吃蛇是久负盛名的游戏,它也和俄罗斯方块,扫雷等游戏位列经典游戏的行列,那贪吃蛇到底是怎么实现的呢?今天,我就用C语言带着大家一起来实现一下这款游戏,从设计到代码的实现可以帮助我们提升编程能力和逻辑能力

web3以太坊开发,前后端交互中涉及到的合约

在web3以太坊开发中,往往大家交流的时候,会涉及到一些合约相关的词汇,这里重点说两个合约,一个是manager合约,另一个是registry合约。

SpringBoot对接口配置跨域设置

在 Spring Boot 应用中,接口配置跨域(Cross-Origin Resource Sharing,CORS)设置是一个常见的需求,特别是当你的前端应用和后端服务部署在不同的域名下时。

android实现倒计时功能_anroid倒计时播报-程序员宅基地

文章浏览阅读611次。Android中的实现CountDownTimer类专门用来实现时间统计 直接使用这个类,或者自定义一个类 class TimeLooper extends CountDownTimer{ //参数为总时间,时间间隔 public TimeLooper(long millisInFuture, long countDownInterval) {_anroid倒计时播报