本次题解格式参考 墨羽魂韶

本文所用的试题:

第十二届蓝桥杯大赛软件赛省赛_CB.pdf

最后编辑时间

2021年4月29日 21:27:46

2022 年 4月 8号 15点13分

填空题答案速览

统一声明

如果不写默认带有常用头文件

如果不表明主函数默认表示在 void solve(){}

默认使用

using namespace std;

ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

using ll = long long;

填空题答案速览

  1. 67108864
  2. 3181
  3. 40257
  4. 2430
  5. 10266837

A. 空间

问题简述

256MB可以存放多少32位二进制整数?

1 Mb = 1024 Kb = 1024 * 1024 b

int = 4B (一个 int 占4比特)

注意用 long long

cout << 1ll * 256 * 1024 * 1024 * 8 / 32 << "\n";

B. 卡片

问题简述

用标有0~9且各有2021张的卡片可以拼到哪个数字

问题分析

直接按位统计, 不足退出即可, 特别注意, 退出循环的那个应该是正好无法达到的, 应该比那个少一

void solve() {
for (int i = 0; i < 10; ++i) a[i] = 2021;
int i = 1;
while (true) {
int tmp = i;
while (tmp) {
--a[tmp % 10], tmp /= 10;
}
bool f = true;
for (int i = 0; f && i < 10; ++i)
if (a[i] < 0) f = false;
if (!f) break;
i++;
}
cout << --i << '\n';
}

C. 直线

问题简述

给定平面上的 20*21 个整点, 问有不同的多少直线?

问题分析

结论而言就是比较K,B值,可以直接模拟,代码如下

const int N = 2e5 + 10;
struct Line {
double k, b;
bool operator<(const Line &t) const {
if (k != t.k) return k < t.k;
return b < t.b;
}
} l[N]; void solve() {
int cnt = 0;
for (int x1 = 0; x1 < 20; ++x1)
for (int y1 = 0; y1 < 21; ++y1)
for (int x2 = 0; x2 < 20; ++x2)
for (int y2 = 0; y2 < 21; ++y2) {
if (x1 != x2) {
double k = (double)(y2 - y1) / (x2 - x1);
double b = y1 - k * x1;
l[cnt++] = {k, b};
}
}
sort(l, l + cnt);
int ans = 1;
for (int i = 1; i < cnt; ++i)
if (fabs(l[i].k - l[i - 1].k) > 1e-8 || fabs(l[i].b - l[i - 1].b) > 1e-8)
ans++;
cout << ans + 20 << '\n'; // 加上20条竖线
}

D. 货物摆放

问题简述

将 2021041820210418 可以分解为多少种 \(A * B * C\)的形式

问题分析

找到所有的因子,然后对因子进行暴力枚举

const ll N = 2021041820210418, mod = 1e3 + 7;
int P[mod], idx = 0;
void solve() {
for (int i = 1; N / i >= i; ++i)
if (N % i == 0) P[idx++] = i;
ll cnt = 0;
for (int i = 0; i < idx; ++i)
for (int j = 0; j < idx; ++j)
for (int k = 0; k < idx; ++k) {
if (1ll * P[i] * P[j] * P[k] == N) ++cnt;
if (N / P[i] != P[i] && P[i] == P[j] * P[k]) ++cnt;
if (N / P[j] != P[j] && P[j] == P[i] * P[k]) ++cnt;
if (N / P[k] != P[k] && P[k] == P[j] * P[i]) ++cnt;
}
cout << cnt << "\n";
}

E. 路径

问题简述

一个无向图, 2021个点, 标号为(1 ~ 2021), 如果两个点的差的绝对值<= 21, 则两点相通, 边长为两点的最大公倍数, 求起点1到2021的最小距离

问题分析

按题目建图, 跑一下SPFA(dijstra 等均可

void solve() {
int n = 2021;
for (int i = 0; i < 2022; ++i)
for (int j = max(i - 21, 0), k = min(i + 21, 2021); j <= k; ++j)
add(i, j, 1ll * i * j / gcd(i, j));
cout << spfa() << '\n';// 赛后听说有人暴力跑 Floyd 也能出答案,但不建议
}

Update: Dijstra and DP

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2025; #define inf 0x3f3f3f3f int e[N][N];
int d[N], dist[N];
bool vis[N]; int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}
int lcm(int a, int b) {return a / gcd(a, b) * b;} int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << fixed << setprecision(20);
memset(e, inf, sizeof(e));
for (int i = 1; i < N; i ++) {
e[i][i] = 0;
for (int j = i + 1; j < N; j ++) {
int w = lcm(i, j);
e[i][j] = e[j][i] = w;
}
}
memset(d, inf, sizeof(d));
memset(vis, false, sizeof(vis));
d[1] = 0; for (int i = 1; i < N; i ++) {
int x = 0 ;
for (int j = 1; j < N; j ++) if (!vis[j] and d[j] < d[x]) x = j;
vis[x] = 1;
for (int j = max(1, x - 21); j <= min(N, x + 21); j ++) {
d[j] = min(d[j], d[x] + e[x][j]);
}
}
cout << d[2021] << "\n";
}

由于边的特殊性(边权为两数的最小公倍数,且两数的绝对值相差不超过21才连通),那么其实从1到某点的最短路径必然是递增的,证明:略(不会)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using namespace std; #define INF 0x3f3f3f3f
#define N 2025
int d[N]; int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}
int lcm(int a, int b) {return a / gcd(a, b) * b;}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << fixed << setprecision(20);
memset(d, INF, sizeof(d));
d[1] = 0;
for (int i = 1; i < N; i ++)
for (int j = i + 1; j < N and j - i <= 21; j ++)
d[j] = min(d[j], lcm(i, j) + d[i]);
cout << d[2021] << "\n";
}

F. 时间显示

问题简述

给出一个整数, 表示1970年1月1日00:00开始经过的毫秒数, 输出对应的时分秒

问题分析

获取到对应的时间, 然后直接使用 printf输出即可

void solve() {
ll time;
cin >> time;
int h = time / (1000 * 60 * 60) % 24;
int m = time / (1000 * 60) % 60;
int s = time / 1000 % 60;
printf("%02d:%02d:%02d", h, m, s);
}

G. 砝码称重

问题简述

给出N个砝码, 重量分别为 \(W_1,W_2,W_3,W_4,...,W_n\), 请问一共可以称出多少不同的重量

问题分析

假设有一个长度为1e6的数组, 表示可以称出的重量, 那么每多一个砝码(重量为k), 那么对于任何一个已经可以称出的重量( \(i\) ), 可以组合得到 \(i-k, k-i, i+k\) 这三种重量

我们只需要维护这个数组即可

const int N = 1e6 + 7;
int W[N] = {1};
void solve() {
int n, t;
cin >> n;
while (n--) {
cin >> t;
for (int i = 0; i < N; ++i) {
// 为了节省空间, 用-1表示在大于i的, 1表示小于等于i的, 0表示无法称出的
if (W[i] == 1) {
// i-t的情况
if (i > t) W[i - t] = 1;
// t-i的情况
if (t > i + i && W[t - i] != 1) W[t - i] = -1;
if (t - i > 0 && W[t - i] != -1) W[t - i] = 1;
// i+t的情况
if (i + t < N && W[i + t] != 1) W[i + t] = -1;
}
if (W[i] == -1) W[i] = 1;
}
}
int cnt = 0;
for (int i = 1; i < N; ++i) cnt += W[i];
cout << cnt << '\n';
}

H. 杨辉三角形

问题简述

给定一个数, 求出是在杨辉三角形的第几个数出现的

问题分析

比赛的时候没什么好的解法,随便找了下规律。用暴力能骗一些分

见注释

// Murabito-B 21/05/01
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int n;
/*
组合数和杨辉三角:第i行第j列的数都是组合数C(i, j) (i,j从0开始)
C(n, 1) = n --> 对应从左向右看斜着的第二列! ---> 一定有解
由于杨辉三角左右对称(C(a, b) == C(a, a-b)),又由于找第一次出现,因此一定在左边,右边可以直接删掉! 1 ---> C(0, 0)
1
1 2 ---> C(2, 1)
1 3 ---> C(2n, n)
1 4 6 ---> C(4, 2)
1 5 10
1 6 15 20 ---> C(6, 3) n最大1e9,C(34, 17) > 1e9, C(32, 16) < 1e9,因此只要枚举前16个斜行即可! 性质:
1. 每一斜行从上到下递增
2. 每一横行从中间到两边依次递减 因此我们直接从中间对称轴倒序二分找起即可! C(r, k)对应的顺序值为:(r + 1) * r / 2 + k + 1 二分的左右端点:l:2k,r:max(n, l)
右端点一定不能比左端点小!
特例:否则当n=1时,会出问题! */
// C(a, b) = a!/b!(a-b)! = a * (a-1) .. b个 / b!
LL C(int a, int b) {
LL res = 1;
for (int i = a, j = 1; j <= b; i--, j++) {
res = res * i / j;
// 大于n已无意义,且防止爆LL
if (res > n) return res;
}
return res;
} bool check(int k) {
// 二分该斜行,找到大于等于该值的第一个数
// 左边界2k,右边界为max(l, n)取二者最大即可!
int l = 2 * k, r = max(n, l);
while (l < r) {
int mid = l + r >> 1;
if (C(mid, k) >= n) r = mid;
else
l = mid + 1;
}
if (C(r, k) != n) return false;
// C(r, k)的从0开始的顺序!
cout << 1ll * (r + 1) * r / 2 + k + 1 << endl;
return true;
} int main() {
cin >> n;
// 从第16斜行枚举即可!
for (int k = 16;; k--)
if (check(k)) break;
return 0;
}

I. 双向排序

问题简述

给定序列 \(a_1,a_2,…,a_n=1,2,…,n,\) 对该序列进行 \(m\)次 操作, 每次可能是对 [1, q]进行降序排列或者对[q, n] 进行升序排列

问题分析

没啥思路, 直接sort骗分了, 不过sort前判断了下当前是否有序, 有序直接调整了

暂未解决

J. 括号序列

问题简述

给定一个括号序列,要求尽可能少地添加若干括号使得括号序列变得合法

问题分析

分为两种特殊情况:

  1. 当左括号或右括号数量全为零, 此时是个卡特兰数
  2. 左括号与右括号相等, 不需要再插入括号

暂未解决

第十二届蓝桥杯C++B组 A~H题题解的更多相关文章

  1. 2019第十届蓝桥杯C++B组题解(赛后重写的,不确保答案正确性,仅供参考)

    先说一下这次的感受吧,我们考场比较乱,开始比赛了,还有的电脑有故障,(向这些人发出同情),第一次认真参加比赛,真正比赛的时候感觉没有那么正式,很乱,各种小问题,(例如博主就没找到题目在哪里,找到后又不 ...

  2. 第八届蓝桥杯java b组第六题

    标题:最大公共子串 最大公共子串长度问题就是:求两个串的所有子串中能够匹配上的最大长度是多少. 比如:"abcdkkk" 和 "baabcdadabc",可以找 ...

  3. 2021年第十二届蓝桥杯javaA组省赛部分题目

    试题 D: 路径 本题总分:10 分 [问题描述] 小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图 中的最短路径. 小蓝的图由 2021 个结点组成,依次编号 1 至 2021. 对 ...

  4. 2019年第十届蓝桥杯c++A组java/c++组题解

    #include<iostream> #include<vector> using namespace std; vector <int > vec; long l ...

  5. 【蓝桥杯】第十二届蓝桥杯砝码称重(Python题解)

    @ 目录 题目 [80分] 思路 知识点 代码 题目 [80分] 你有一架天平和N个砝码,这N个砝码重量依次是W1,W2,--,WN请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边. ...

  6. 第六届蓝桥杯java b组第五题

    九数组分数 1,2,3…9 这九个数字组成一个分数,其值恰好为1/3,如何组法? 下面的程序实现了该功能,请填写划线部分缺失的代码. public class A { public static vo ...

  7. 第三届蓝桥杯Java高职组决赛第一题

    题目描述: 看这个算式: ☆☆☆ + ☆☆☆ = ☆☆☆ 如果每个五角星代表 1 ~ 9 的不同的数字. 这个算式有多少种可能的正确填写方法? 173 + 286 = 459 295 + 173 = ...

  8. 2018年蓝桥杯java b组第八题

    标题:日志统计 小明维护着一个程序员论坛.现在他收集了一份"点赞"日志,日志共有N行.其中每一行的格式是: ts id 表示在ts时刻编号id的帖子收到一个"赞" ...

  9. 2018年蓝桥杯java b组第七题

    标题:螺旋折线 如图p1.pgn所示的螺旋折线经过平面上所有整点恰好一次. 对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度. 例如dis(0, ...

  10. 2018年蓝桥杯java b组第六题

    标题:递增三元组 给定三个整数数组A = [A1, A2, ... AN], B = [B1, B2, ... BN], C = [C1, C2, ... CN],请你统计有多少个三元组(i, j, ...

随机推荐

  1. 【Spring Boot】【外包杯】学习day02 | 快速搭建一个Spring Boot项目

    1.

  2. AI换脸利器!Roop下载分享

    ​ 前段时间给大家介绍过换脸界最强的Rope,感兴趣的小伙伴可以戳戳手指 传送门:https://blog.csdn.net/S_eashell?spm=1011.2415.3001.5343 今天要 ...

  3. 深度学习前沿 | 利用GAN预测股价走势

    本文是对于medium上Boris博主的一篇文章的学习笔记,这篇文章中利用了生成对抗性网络(GAN)预测股票价格的变动,其中长短期记忆网络LSTM是生成器,卷积神经网络CNN是鉴别器,使用贝叶斯优化( ...

  4. Javascript Ajax总结——其他跨域技术之图像Ping和JSONP

    在CORS出现之前,为实现跨域Ajax通信,开发人员利用DOM中能够执行跨域请求的功能,在不依赖XHR对象的情况下也能发送某种请求.1.图像Ping这里使用<img>标签.一个网页可以从任 ...

  5. 【OpenCV】在MacOS上源码编译OpenCV

    前言 在做视觉任务时,我们经常会用到开源视觉库OpenCV,OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,它具有C++,Python,Java和MATLA ...

  6. 学会@ConfigurationProperties月薪过三千

    学习 @ConfigurationProperties 之前我们需要一些前置知识点: @Value是个什么东西 首先明确:@ConfigurationProperties 是 SpringBoot 注 ...

  7. DVWA Cross Site Scripting (XSS) 跨站脚本攻击

    文章目录 DVWA_XSS(Stored) 存储性XSS 1.Low 2.Medium 3.High 4.Impossible XSS平台 DVWA_XSS(Stored) 存储性XSS 一句话概括: ...

  8. 踩坑ffmpeg录制的mp4无法在浏览器上播放

    前言 使用ffmpeg编译好的程序在电脑上进行音视频转换,可以参考这篇:<windows电脑FFmpeg安装教程手把手详解_windows安装ffmpeg>,而我们要做的是在游戏引擎中集成 ...

  9. Spring Boot结合Element UI前后端分离的aixos的简单操作

    1:axios是什么? 基于promise用于浏览器和node.js的http客户端 axios官网:http://www.axios-js.com/  2:准备工作: 安装axios:npm ins ...

  10. libGDX游戏开发之字体样式(七)

    libGDX游戏开发之字体样式(七) libGDX系列,游戏开发有unity3D巴拉巴拉的,为啥还用java开发?因为我是Java程序员emm-国内用libgdx比较少,多数情况需要去官网和googl ...