Misaka-xxw的博客

昨日种种,皆成今我

🚧施工中🚧

排序之间的比较

排序算法 时间复杂度 空间复杂度 稳定性 适合链式存储?
最好情况 平均情况 最坏情况
直接插入排序 折半插入:❌;直接插入:✅
冒泡排序
简单选择排序
希尔排序
快速排序
堆排序
二路归并排序
基数排序

习题

有序的排序

(没好好看题全做错了)
对 n 个基本有序的整数进行排序:

  1. 若采用插入排序算法,则时间和空间复杂度分别为( );
  2. 若采用快速排序算法,则时间和空间复杂度分别为( )。

正确答案

  1. 插入排序:时间复杂度 ,空间复杂度 .
  2. 快速排序:时间复杂度 ,空间复杂度 .

解析

  1. 插入排序

    • 时间复杂度:当数据基本有序时,插入排序只需进行少量的比较和移动操作,因此时间复杂度为
    • 空间复杂度:插入排序只需常数级的额外空间(如临时变量等),因此空间复杂度为 .
  2. 快速排序

    • 时间复杂度:快速排序在最坏情况下(如数据已完全有序),每次划分只能将数组分成一个元素和 个元素的两部分,此时递归深度为 ,时间复杂度为 .
    • 空间复杂度:快速排序主要是在原数组上进行操作,无需额外的存储空间,因此空间复杂度为 .

这不是某大学期末考试考的东西,不要背。

信息安全

信息的特性:

密码体制和加密算法

  • 对称加密/共享密钥
    • 加密密钥与解密密钥都是用相同密钥
    • 对大量明文加密时,考虑效率,一般采用对称加密
    • 常用算法:AES、DES、3DES、RC-5
  • 非对称加密/公钥加密
    • 使用不同的加密密钥与解密密钥。公钥加密,私钥解密
    • 常见算法:RSA、ECC、EIGamma、背包算法
  • 流加密
    • 加密和解密双方使用相同伪随机加密数据流作为密钥,明文数据每次与密钥数据流顺次对应加密,得到密文数据流
    • 常见算法:RC4、ORYX、SEAL
  • 分组加密
    • 将明文分为等长的模块,使用确定的算法和对称密钥对每组分别加密解密
    • 常见算法:DES、AES
  • 数字摘要/消息摘要算法
    • 一个唯一对应一个消息或文本的固定长度的值
    • 单向Hash加密函数
    • 常见算法:MD5、SHA、MAC

X.509数字证书推荐使用的密码算法:RSA
国密SM2数字证书采用的密码算法:ECC

数字签名与数字证书

数字签名

  • 功能 :保证信息的完整性不可否认性。确保信息在传输过程中未被篡改,同时让接收方确认消息确实来自发送方且发送方无法否认其发送过该消息。
  • 密钥使用 :发送方使用自己的私钥对信息生成数字签名,接收方用发送方的公钥验证签名,验证通过则确认信息完整性和身份。

数字证书

  • 功能 :用于证明身份和确保公钥可信度。就像网络上的身份证,由权威机构颁发,验证持有者身份及公钥归属。
  • 密钥使用 :证书中包含公钥,证书颁发机构用自己的私钥对证书签名。接收方收到证书后,用颁发机构公钥验证证书合法性,验证通过则可安全使用证书中的公钥。

防火墙

防火墙

  • 控制进出网络的数据包和数据流向
  • 提供流量信息的日志和审计
  • 隐藏内部IP以及为网络结构细节
  • 记录访问工程、包过滤、代理

在出口防火墙上配置ACL(Access Control List,访问控制列表)功能可以组织外部未授权用户访问内部网络。

防火墙三个区域,受保护程度:外网<DMZ<内网
通常把Web服务器置于DMZ区(隔离区、非军事化区)

包过滤防火墙对网络层

一些网络协议

IPsec
工作在网络层,主要用于在两台设备之间建立加密连接,保护数据传输不被窃听和篡改。常用于虚拟专用网络(VPN),让远程办公人员安全访问公司内部网络。

PPP(点对点协议)
位于数据链路层,用于在点对点链路上传输数据,比如拨号上网。它负责建立和维护连接,进行数据封装等,为上层协议提供服务。
PPP的安全协议是CHAP,密文采用MD5加密。

HTTPS
是加密版的 HTTP,在应用层工作。通过加密和身份验证,保护用户访问网站时的数据安全,比如网上购物、银行转账等场景,防止信息泄露。

TLS(传输层安全协议)
工作在传输层,是 HTTPS 的基础安全协议。用于在互联网通信中提供加密和身份验证,确保数据传输的机密性和完整性,广泛应用于各种网络应用。

未分类知识

有效防止SQL注入的手段:

  • 对用户输入做关键字过滤
  • Web应用防火墙
  • 定期扫描系统漏洞并及时修复

入侵检测技术有:专家系统、模型检测、简单匹配

知识产权的分类:

使

知识产权的特点:

  • 无形性
  • 双重性
  • 确定性
  • 独占性
  • 地域性
    • 本国法律保护
  • 时间性

《计算机软件保护条例》保护对象:

  • 软件程序
    • 源程序
    • 目标程序
  • 文档

软件著作权无明确规定,由开发者所有。

同样的发明只能授予一项专利

专利权:谁先申请就给谁;同时申请则商量
商标权:谁先申请就给谁;同时申请,谁先使用就给谁;均未使用或者无法证明,先协商;协商不了则抽签

烟草必须注册商标

著作权时间期限

  • 永久保护:
    • 普通著作权作品的署名权、修改权、保护作品完整权
    • 软件著作权的署名权、修改权
  • 其他作品保护期限是作者终身及其死后50年
  • 商标权可以续延长
  • 商业秘密权保密期限不确定

普通

软件名 功能 官网
Snipaste 截图和剪贴板置顶 https://zh.snipaste.com/download.html
Color 屏幕取色板 https://www.den4b.com/news/3044/colors-3-2
ScreenToGif Gif录屏、编辑和转换,很全面 https://www.screentogif.com/downloads
Ultimate Vocal Remover 强大的人声分离和去除混音软件 https://ultimatevocalremover.com/
OpenUtau 开源歌声合成,古法调教或鬼畜 https://www.openutau.com/#download
Joplin 多设备Markdown格式记事本 https://joplinapp.org/download/

专业

软件名 功能 官网
filezilla ftp https://www.filezilla.cn/
MobaXterm ssh https://mobaxterm.mobatek.net/
IDA 反汇编 https://hex-rays.com/ida-free

数学符号

基本数学符号

符号 LaTeX 命令 符号 LaTeX 命令 符号 LaTeX 命令
± \pm \mp × \times
÷ \div \sqrt \sqrt[3]
! ! ? ? \sum
\prod \int \iint
\iiint \oint \bigcup
\bigcap \bigvee \bigwedge

希腊字母

小写字母符号 小写字母LaTeX命令 大写字母符号 大写字母LaTeX命令
α \alpha Α \Alpha
β \beta Β \Beta
γ \gamma Γ \Gamma
δ \delta Δ \Delta
ε \epsilon Ε \Epsilon
ζ \zeta Ζ \Zeta
η \eta Η \Eta
θ \theta Θ \Theta
ι \iota Ι \Iota
κ \kappa Κ \Kappa
λ \lambda Λ \Lambda
μ \mu Μ \Mu
ν \nu Ν \Nu
ξ \xi Ξ \Xi
π \pi Π \Pi
ρ \rho Ρ \Rho
σ \sigma Σ \Sigma
τ \tau Τ \Tau
υ \upsilon Υ \Upsilon
φ \phi Φ \Phi
χ \chi Χ \Chi
ψ \psi Ψ \Psi
ω \omega Ω \Omega

微积分符号

符号 LaTeX 命令 符号 LaTeX 命令 符号 LaTeX 命令
\int \iint \iiint
\oint \partial \frac{d}{dx}
\nabla lim \lim \infty

集合论符号

符号 LaTeX 命令 符号 LaTeX 命令 符号 LaTeX 命令
\in \notin \subset
\supset \subseteq \supseteq
\cap \cup \emptyset
Δ \Delta Φ \Phi Γ \Gamma

逻辑符号

符号 LaTeX 命令 符号 LaTeX 命令 符号 LaTeX 命令
\land \lor ¬ \neg
\rightarrow \leftarrow \Rightarrow
\Leftarrow \forall \exists

线性代数符号

符号 LaTeX 命令 符号 LaTeX 命令 符号 LaTeX 命令
\oplus \otimes \odot
\perp \angle \cdot
\parallel \land \lor
\rightharpoonup \leftharpoonup
A^T A^{-1} \operatorname{rank}

矩阵和行列式

符号 LaTeX 命令 符号 LaTeX 命令 符号 LaTeX 命令
[ ] \begin{pmatrix}...\end{pmatrix} [ ] \begin{bmatrix}...\end{bmatrix} [ ] \begin{Bmatrix}...\end{Bmatrix}
[ ] \begin{vmatrix}...\end{vmatrix} [ ] \begin{Vmatrix}...\end{Vmatrix}
[ ] \begin{matrix}...\end{matrix}

其他常见符号

符号 LaTeX 命令 符号 LaTeX 命令 符号 LaTeX 命令
\approx \equiv \leq
\geq \neq ± \pm
\mp \partial \nabla

上下标和分数

符号 LaTeX 命令 符号 LaTeX 命令
x^2 y_i
z^{i+1}_j \frac{a}{b}

箭头

符号 LaTeX 命令 符号 LaTeX 命令 符号 LaTeX 命令
\leftarrow \rightarrow \leftrightarrow
\Leftarrow \Rightarrow \Leftrightarrow
\longleftarrow \longrightarrow \longleftrightarrow
\Longleftarrow \Longrightarrow \Longleftrightarrow
\uparrow \downarrow \updownarrow
\Uparrow \Downarrow \Updownarrow
\mapsto \hookrightarrow \hookleftarrow
\rightharpoonup \leftharpoondown \rightleftharpoons
\nearrow \swarrow \nwarrow
\searrow

关系代数

中文 符号 LATEX命令
投影 Π \Pi
选择 σ \sigma
重命名 ρ \rho
聚合函数 G \mathcal{G}
\cup
\cap
自然连接 \bowtie\Join
左外连接 (直接复制吧)
右外连接 (同上)
全外连接 (同上)
笛卡尔乘积 × \times
÷ \div
赋值 \leftarrow
条件并列 \land\vee
¬ \neg
存在 \exists
对所有 \forall

参考

Not just for exam.

参考:林子雨老师的《数据库系统原理》,以及《软件设计师教程》

写在前面:刻在DNA里的学生选课数据库

本章的所有实例都以学生选课数据库为基础,该数据库包括5个表:

  1. 学生表Student(Sno, Sname, Ssex, Sage, Sdept);
  2. 课程表Course(Cno, Cname, Cpno, Ccredit);
  3. 学生选课表SC(Sno, Cno, Grade);
  4. 教师表Teacher(Tno, Tname, Tsex, Tage);
  5. 授课表TC(Tno, Cno)。

每一个表的第一列都是主码。

Student

Sno Sname Sex Sage Sdept
2024001 林书凡 18 MA
2024002 李欣然 19 IS
2024003 王武义 20 CS
2024004 苏文甜 19 CS

Course

Cno Cname Cpno Ccredit
1 大数据 3 2
2 操作系统 5 4
3 数据库 5 4
4 编译原理 NULL 4
5 编程语言 NULL 2
6 数据挖掘 3 2

SC

Sno Cno Grade
2024001 1 97
2024001 2 78
2024001 3 86
2024002 2 85
2024002 3 77

Teacher

Tno Tname Tsex Tage
97001 林形文 45
97002 司马鹰松 33
97003 王明天 38
97004 马晓燕 36
97005 张勇 51

TC

Tno Cno
97001 1
97001 3
97002 2
97003 4
97004 5
97004 6
97005 6

数据库概述

关系数据库

关系运算

逻辑表达式

运算符 含义
比较运算符 > 大于
>= 大于等于
< 小于
<= 小于等于
= 等于
<> 不等于
逻辑运算符 ¬

八种关系运算

  1. 并(Union)

    • 符号:
    • 作用:合并两个关系中的元组,去除重复的元组。
    • 表示:,表示关系R和关系S的并集。
  2. 交(Intersection)

    • 符号:
    • 作用:找出两个关系中共有的元组。
    • 表示:,表示关系R和关系S的交集。
  3. 差(Difference)

    • 符号:
    • 作用:从第一个关系中移除与第二个关系中相同的元组。
    • 表示:,表示关系R中不在关系S中的元组。
  4. 选择(Selection)

    • 符号:
    • 作用:从关系中选择满足特定条件的元组()。
    • 表示:,表示从关系R中选择满足条件的元组。
  5. 投影(Projection)

    • 符号:
    • 作用:从关系中选择特定的属性
    • 表示:,表示从关系R中选择指定的属性列。
  6. 连接(Join)

    • 符号:
    • 作用:将两个关系中满足特定条件的元组合并成一个新的关系。
    • 表示:,表示关系R和关系S的自然连接。
      • 条件连接θ-连接):,其中是连接条件,可以是等比较运算符,表示基于这些条件的连接。
      • 外连接(Outer Join):当两个关系中没有完全匹配的元组时,外连接可以返回其中一个关系的所有元组,以及另一个关系中匹配的元组。如果另一个关系中没有匹配的元组,则结果中对应的字段为NULL
        • 左外连接(Left Outer Join):返回左关系(R)的所有元组,即使在右关系(S)中没有匹配的元组。如果右关系中没有匹配的元组,则结果中右关系的部分为NULL
          • 表示:Double subscripts: use braces to clarifyR \underset{A \theta B}{\Join}_{\text{L}} S 或者
        • 右外连接(Right Outer Join):返回右关系(S)的所有元组,即使在左关系(R)中没有匹配的元组。如果左关系中没有匹配的元组,则结果中左关系的部分为NULL
          • 表示:Double subscripts: use braces to clarifyR \underset{A \theta B}{\Join}_{\text{R}} S 或者
        • 全外连接(Full Outer Join):返回两个关系中任一关系的所有元组,无论另一个关系中是否有匹配的元组。如果另一个关系中没有匹配的元组,则结果中对应的字段为NULL
          • 表示:Double subscripts: use braces to clarifyR \underset{A \theta B}{\Join}_{\text{FULL}} S 或者
  7. 笛卡尔积(Cartesian Product)

    • 符号:×
    • 作用:将两个关系中的每个元组与另一个关系中的每个元组配对,形成所有可能的组合。
    • 表示:R × S,表示关系R和关系S的笛卡尔积。
  8. 除(Division)

    • 符号:÷
    • 作用:找出能够与第二个关系中所有元组配对的第一个关系中的元组。
    • 表示:R ÷ S,表示关系R中能够与关系S中所有元组配对的元组。

简单理解:

  • 选择是取行,投影是取列。
  • 自然连接中,如果两个表有相同的列名,那两个表相同列名的列,具体值也要相同,才能配对。所以左右表都有可能会删去一些不匹配的行。
  • 左外连接中,左边表的所有行都会被保留,即使右边表中没有匹配的行,此时右边表对应的位置会用NULL填充。
  • 右外连接同理。
  • 全外连接中,左右两边表的所有行都会被保留,无论是不是匹配,当有一边没有匹配时,那一边对应的位置会用NULL填充。
  • 笛卡尔积就是两个表直接不由分说地连, 大小的表A和 大小的的表B,笛卡尔积得到的表C,与连接不同。
  • 除如图:图片

关系运算的sql表示

  1. 并(Union)

    1
    2
    3
    SELECT column_name(s) FROM table1
    UNION
    SELECT column_name(s) FROM table2;
  2. 交(Intersection)

    1
    2
    3
    SELECT column_name(s) FROM table1
    INTERSECT
    SELECT column_name(s) FROM table2;
  3. 差(Difference)

    1
    2
    3
    SELECT column_name(s) FROM table1
    EXCEPT
    SELECT column_name(s) FROM table2;
  4. 选择(Selection)

    1
    2
    SELECT * FROM table
    WHERE condition;
  5. 投影(Projection)

    1
    SELECT column_names FROM table;
  1. 连接(Join)
  • 自然连接(Natural Join)

    1
    2
    SELECT * FROM table1
    NATURAL JOIN table2;
  • 条件连接(θ-连接)

    1
    2
    SELECT * FROM table1
    JOIN table2 ON condition;
  • 外连接(Outer Join)

    • 左外连接(Left Outer Join)

      1
      2
      SELECT * FROM table1
      LEFT JOIN table2 ON condition;
    • 右外连接(Right Outer Join)

      1
      2
      SELECT * FROM table1
      RIGHT JOIN table2 ON condition;
    • 全外连接(Full Outer Join)

      1
      2
      SELECT * FROM table1
      FULL JOIN table2 ON condition;
  1. 笛卡尔积(Cartesian Product)

    1
    SELECT * FROM table1, table2;
  2. 除(Division)

    1
    2
    3
    4
    5
    SELECT column_names FROM table1
    WHERE NOT EXISTS (
    SELECT * FROM table2
    WHERE table1.column = table2.column
    );

习题

学生数据库

已知数据库

  1. 学生表S(Sno, Sname, Ssex, Sage, Sdept);
  2. 课程表C(Cno, Cname, Cpno, Ccredit);
  3. 学生选课表SC(Sno, Cno, Grade);

完成:

  1. 检索选修课程名为“数学”的学生的学号和姓名。
  2. 检索至少选修了课程号为 1 和 3 的学生的学号。
  3. 检索选修了“操作系统”或“数据库”课程的学生的学号和姓名。
  4. 检索年龄在 18~20 之间(含 18 和 20)的女生的学号、姓名及年龄。
  5. 检索选修了“数据库”课程的学生的学号、姓名及成绩。
  6. 检索选修了全部课程的学生的姓名所在系。
  7. 检索选修课程包括 1042 学生所学课程的学生的学号。
  8. 检索不选修 2 课程的学生的姓名和所在系。

My answer:
打latex也太难了吧,我直接开始歪歪地手写
图片

关系数据库标准语言SQL

视图在数据字典中保存的是视图定义

关系数据库编程

关系数据库安全和保护

关系数据库的规范化理论

关系模式中可能存在的冗余和异常问题

  1. 数据冗余
  2. 不一致性
  3. 插入异常
  4. 删除异常

    函数依赖

    定义

  5. 函数依赖:设 为任一给定关系,如果对于 中属性 的每一个值, 中的属性 只有唯一值与之对应,则称 函数决定 ,或 函数依赖于 X,记作 。其中,X 称为决定因素。反之,对于关系 中的属性 ,若 不能函数决定 Y,则其符号记作
  6. 平凡的函数依赖:设 是一个函数依赖,若 ,则称 是一个平凡的函数依赖
  7. 完全函数依赖:设 是一个函数依赖,并且对于任何 都不成立,则称 是一个完全函数依赖,记作
  8. 部分函数依赖:设 是一个函数依赖,但不是完全函数依赖,则称 是一个部分函数依赖,记作
  9. 传递函数依赖:设 是一个关系模式,,如果 ,且 ,则称 传递函数依赖
  10. 候选码:设 为任一给定关系模式, 为其所含的全部属性集合, 的子集,若有完全函数依赖 ,则 的一个候选码
  11. 主属性和非主属性:包含在任何一个候选码中的属性为主属性,否则为非主属性。

理解

  1. 普通函数依赖(X→Y)
    想象你的身份证号码(X)就像一把万能钥匙,它能直接确定你的姓名(Y)、性别、出生地。只要知道身份证号,其他信息都能唯一确定。
    例如:学号→姓名,就像每个学号对应唯一的学生。

  2. 平凡依赖 vs 非平凡依赖

    • 平凡就像「已知父亲名字,自然知道家族姓氏」(因为姓氏已经是父亲名字的一部分)
    • 非平凡像「快递单号与包裹信息」,单号能唯一确定收件人的电话(例如单号 SF123456 对应电话 13800001111),但电话不是单号的子集,这也是​​非平凡函数依赖
  3. 完全依赖 vs 部分依赖
    完全依赖就像「用完整钥匙开锁」:

    • 成绩完全依赖(学号+课程号)组合,单独学号或课程号都不够

    部分依赖像「用半截钥匙就能开锁」:

    • 如果课程名称只依赖课程号(而课程号是主键的一部分),就是部分依赖
  4. 传递依赖(连锁反应)
    学号→系号→系主任,系主任像被「间接遥控」确定。这会导致数据冗余(多个学生重复存储系主任信息)

  • 候选码就像「能开所有锁的最小钥匙组合」:

    • 比如(学号+课程号)组合才能确定成绩,单独一个都不行
  • 主属性是所有候选码中的零件:

    • 如果候选码是学号,那么学号就是主属性;如果候选码是(学号+身份证号),两者都是主属性

范式

第一范式(1NF)

如果关系模式 的每一个 属性对应的域值都是不可再分的,称模式 属于第一范式,记作 。若数据库模式 中的每个关系模式都是 ,则数据库模式

最基本的要求,就是表中的每个属性都不可再分。例如,学生信息表中,每个学生的姓名、年龄、性别等都是不可再分的。

第二范式(2NF)

如果关系模式 ,并且每个非主属性都完全函数依赖于 的码,则

不能有部分依赖。例如,在选课表中,学生成绩应该依赖于学号和课程号的组合,而不是单独依赖学号或课程号。

第三范式(3NF)

关系模式 R 中若不存在这样的码 、属性组 及非主属性 ,使得 成立,则称

例如,学生表中的成绩不能依赖于学生的姓名,因为姓名不是码。

Boyce-Codd范式(BCNF)

,而且R中没有任何属性传递函数依赖于R中的码,则关系模式

第四范式(4NF)

了解一下就可以了。

第五范式(5NF)

了解一下就可以了。

理解

  1. 1NF(基础版)
    要求:每个字段都是最小单元,不能拆。
    错误示范:把「联系电话」写成 “13800001111,13800002222”(应拆分成多行)

  2. 2NF(消灭半吊子依赖)
    必须消灭部分依赖。比如选课表中:

    • 错误:把课程名称和成绩都放在同一张表(课程名称只依赖课程号,不依赖学号)

    • 正确:拆分成「选课表(学号+课程号+成绩)」和「课程表(课程号+课程名称)」

  3. 3NF(斩断连锁依赖)
    禁止传递依赖。比如学生表里直接存系主任名字:
    • 错误:学生表包含系号→系主任
    • 正确:拆分成「学生表(学号+系号)」和「院系表(系号+系主任)」
  4. BCNF(加强版3NF)
    连主属性都不能有传递依赖。举个极端例子:
    • 假设每个老师只教一门课,每门课有多个老师
    • 错误表:(老师ID,课程)主键是老师ID,但课程→教室(课程不是主键)
    • 正确:拆分成「老师-课程表」和「课程-教室表」

举个综合例子(学生选课系统):
原始混乱表
| 学号 | 姓名 | 课程号 | 课程名 | 成绩 | 系名 | 系主任 |
|—-|—-|—-|—-|—-|—-|—-|
| 001 | 张三 | C01 | 数学 | 90 | 计算机系 | 李主任 |

问题分析:

  1. 课程名只依赖课程号(违反2NF)
  2. 系主任依赖系名,系名依赖学号(传递依赖,违反3NF)

助记小漫画(但是记的可能不是数据库知识点)

</details>

规范化后:

  • 学生表(学号,姓名,系名)3NF

  • 课程表(课程号,课程名)2NF

  • 选课表(学号,课程号,成绩)2NF

  • 院系表(系名,系主任)3NF

这样修改后,更新系主任信息只需要修改院系表中的一个位置,避免了数据冗余和更新异常。

模式分解

习题

2021上半年软考 42题

给定关系R(U,F),其中U={A,B,C,D,E,H},F={(A→B,B→DH,A→H,C→E)}。关系有( ),F中( )。

问题1:

  • [ ] A. 1个候选码A
  • [ ] B. 2个候选码A、B
  • [x] C. 1个候选码AC
  • [ ] D. 2个候选码A、C

问题2:

  • [ ] A. 不存在传递依赖,但存在冗余函数依赖
  • [ ] B. 既不存在传递依赖,也不存在冗余函数依赖
  • [ ] C. 存在传递依赖A→D和A→H,但不存在冗余函数依赖
  • [x] D. 存在传递依赖A→D和A→H,并且还存在冗余函数依赖

算法

日期题: datetime

日期差值填空

众所周知,2025 年是完全平方年,因为
定义一个年份 是完全平方年当且仅当存在一个正整数 使得
今天是 2025 年 3 月 29 日,现在我们想知道距离下一个完全平方年的 1 月 1 日还有几天(即从 2025 年 3 月 29 日 0 时到下次完全平方年的 1 月 1 日 0 时,例如:从 3 月 29 日 0 时到 3 月 30 日 0 时算 1 天)。

1
2
3
4
from datetime import datetime as dt
a=dt(2025,3,29,0,0,0)
b=dt(46**2,1,1,0,0,0)
print((b-a).days)

P10385 [蓝桥杯 2024 省 A] 艺术与篮球

小蓝决定根据日期的笔画数来安排自己的练习。首先,他会将当天的日期按照 YYYYMMDD 的格式
转换成一个 位数,然后将这 位数对应到汉字上,计算这些汉字的总笔画数。如果总笔画数超过 ,他就去练习篮球;如果总笔画数不超过 ,他就去练习书法。
例如,在 日这天,日期可表示为一个 位数字 ,其转换为汉字是“二零二四零一零一”。日期的总笔画数为 ,因此在这天,小蓝会去练习书法。
以下是汉字的笔画数对照表:

汉字 笔画数 汉字 笔画数

现在,请你帮助小蓝统计一下,在 日到
这段时间内,小蓝有多少天是在练习篮球?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from datetime import datetime,timedelta
a=datetime(2000,1,1,0,0,0)
b=datetime(2024,4,13,0,0,0)
c=a
d=timedelta(days=1)
bh=[13,1,2,3,5,4,4,2,2,2]
s=0
def cnt(x,n):
ret=0
for i in range(n):
ret+=bh[x%10]
x//=10 # 注意python除法
return ret

while c<=b:
s+=1 if cnt(c.year,4)+cnt(c.month,2)+cnt(c.day,2)>50 else 0
c+=d

print(s)

大数/高精度题: decimal

最高位之和

对于正整数 ,设 在十进制下的最高非零位的值, 在十进制下的最高非零位的值,求所有可能的作为 的值的和。相同的值只计算一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from decimal import Decimal
two=Decimal('2')
five=Decimal('5')
s=set()
def high(x):
while x>9:
x//=10
return x

for i in range(50000):
try:
s.add(high(two)*high(five))
two*=2
five*=5
# print(two,five)
except Exception as e:
# print(str(e))
break
res=0
for i in s:
res+=i
print(res)

对拍

待测程序

待测程序test.cpp

1
2
3
4
5
6
7
8
9
#include<bits/stdc++.h>
using namespace std;
int main()
{
freopen("input.txt","r",stdin);
freopen("output1.txt","w",stdout);
//待测程序
return 0;
}

对拍程序

对拍程序bl.cpp

1
2
3
4
5
6
7
8
9
#include<bits/stdc++.h>
using namespace std;
int main()
{
freopen("input.txt","r",stdin);
freopen("output2.txt","w",stdout);
//待测程序
return 0;
}

Python简易评测机

没用过,先放一个在这儿
python简易对拍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import os
import random
import subprocess
import time
import filecmp

def test():
with open("input.txt", "w") as f:
'''
生成随机数据,例
n = random.randint(1, 100)
f.write(f"{n}\n")
for _ in range(n):
l = random.randint(1, 100)
r = random.randint(1, 100)
f.write(f"{l} {r}\n")
'''
start_time=time.time()
subprocess.run(["test.exe"], shell=True) # 测试
print(f"用时{time.time()-start_time:.3f}s")
subprocess.run(["bl.exe"], shell=True) # 对拍
return filecmp.cmp("output1.txt", "output2.txt")

random.seed(time.time())
for i in range(100): # 测试数量
print(f"运行测试例 {i}...")
if not test():
print("测试例 {i} 失败")
exit(0)
print("通过")

参考:https://blog.csdn.net/Mibbp/article/details/124012372

算了,寒假里做几道放几道呗

P8740 [蓝桥杯 2021 省 A] 填空问题

题目描述

试题 A:卡片

【问题描述】

小蓝有很多数字卡片,每张卡片上都是数字

小蓝准备用这些卡片来拼一些数,他想从 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。

小蓝想知道自己能从 拼到多少。

例如,当小蓝有 张卡片,其中 张,则小蓝可以拼出 ,但是拼 时卡片 已经只有一张了,不够拼出

现在小蓝手里有 的卡片各 张,共 张,请问小蓝可以从 拼到多少?

提示:建议使用计算机编程解决问题。

【答案提交】

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

试题 B:直线

【问题描述】

在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。

给定平面上 个整点 ,即横坐标是 (包含 ) 之间的整数、纵坐标是 (包含 ) 之间的整数的点。这些点一共确定了 条不同的直线。

给定平面上 个整点 ,即横坐标是 (包含 ) 之间的整数、纵坐标是 (包含 ) 之间的整数的点。请问这些点一共确定了多少条不同的直线。

【答案提交】

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

试题 C :货物摆放

【问题描述】

小蓝有一个超大的仓库,可以摆放很多货物。

现在,小蓝有 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、 宽、高。

小蓝希望所有的货物最终摆成一个大的立方体。即在长、宽、高的方向上分别堆 的货物,满足

给定 ,请问有多少种堆放货物的方案满足要求。

例如,当 时,有以下 种方案:

请问,当 (注意有 位数字) 时,总共有多少种方案?

提示:建议使用计算机编程解决问题。

【答案提交】

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

试题 D:路径

【问题描述】

小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。

小蓝的图由 个结点组成,依次编号

对于两个不同的结点 ,如果 的差的绝对值大于 ,则两个结点之间没有边相连; 如果 的差的绝对值小于等于 ,则两个点之间有一条长度为 的最小公倍数的无向边相连。

例如:结点 和结点 之间没有边相连; 结点 和结点 之间有一条无向边,长度为 ; 结点 和结点 之间有一条无向边,长度为

请计算,结点 和结点 之间的最短路径长度是多少。

提示:建议使用计算机编程解决问题。

【答案提交】

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

试题 E:回路计数

【问题描述】

蓝桥学院由 栋教学楼组成,教学楼编号 。对于两栋教学楼 ,当 互质时, 之间有一条走廊直接相连,两个方向皆可通行,否则没有直接连接的走廊。

小蓝现在在第一栋教学楼,他想要访问每栋教学楼正好一次,最终回到第一栋教学楼(即走一条哈密尔顿回路),请问他有多少种不同的访问方案? 两个访问方案不同是指存在某个 ,小蓝在两个访问方法中访问完教学楼 后访问了不同的教学楼。

提示:建议使用计算机编程解决问题。

解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
using ll = long long;
using ull = unsigned long long;
//==================== 1 ====================
void solve1()
{
int a[10];
for (int i = 0; i <= 9; i++)
a[i] = 2021;
for (int i = 1;; i++)
{
for (int j = i; j; j /= 10)
{
if (a[j % 10] == 0)
{
cout << i - 1 << endl;
return;
}
--a[j % 10];
}
}
}
//==================== 2 ====================
int gcd(int x, int y)
{
return x % y == 0 ? y : gcd(y, x % y);
}
void solve2()
{
int n = 20, m = 21;
ull ans = 0ll; // row,col
for (int a = 1; a < n; a++)
{
for (int b = 1; b < m; b++)
{
if (gcd(a, b) != 1)
continue;
ans += (n - a) * (m - b);
if (a * 2 <= n && b * 2 <= n)
{
ans -= (n - 2 * a) * (m - 2 * b);
}
}
}
ans *= 2;
ans += (n + m);
cout << ans << endl;
}
//==================== 3 ====================
typedef pair<ull, ull> pp;
ull ans3 = 0;
map<pp, bool> mp;
vector<ull> yz; // 因子
void dfs3(pp p, int d)
{
if (d == yz.size())
{
if (!mp[p])
{
mp[p] = true;
ans3++;
}
return;
}
dfs3(pp(p.first, p.second), d + 1);
dfs3(pp(p.first * yz[d], p.second), d + 1);
dfs3(pp(p.first, p.second * yz[d]), d + 1);
}
void solve3()
{
ull n = 2021041820210418;
for (int i = 2; i <= n;)
{
if (n % i == 0)
{
// cout<<i<<',';
yz.push_back(i);
n /= i;
}
else
{
i++;
}
}
// 2,3,3,3,17,131,2857,5882353
dfs3(pp(1, 1), 0);
cout << ans3 << endl;
}
//==================== 4 ====================
typedef pair<int, int> pint;
void solve4()
{
int n = 2021;
vector<vector<pint>> g(2022);
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= i + 21 && j <= n; j++)
{
int w = i * j / gcd(i, j);
g[i].push_back(pint(w, j));
g[j].push_back(pint(w, i));
}
}
// dijsktra
const int inf = INT_MAX;
vector<int> dis(n + 1, inf);
vector<bool> vis(n + 1, false);
dis[1] = 0;
priority_queue<pint, vector<pint>, greater<>> pq;
pq.push(pint(0, 1));
while (!pq.empty())
{
int u = pq.top().second;
pq.pop();
if (!vis[u])
{
vis[u] = true;
for (auto [w, v] : g[u])
{
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if (!vis[v])
pq.push(pint(dis[v], v));
}
}
}
}
cout << dis[2021] << endl;
}
//==================== 5 ====================
ull ans5;
int ok;
bool have[22][22];
ull f[1 << 21][22]; // 走的序列,到下一个点
void solve5()
{
for (int i = 1; i < 21; i++)
{
for (int j = i + 1; j <= 21; j++)
{
if (gcd(i, j) == 1)
{
have[i][j] = have[j][i] = true;
}
}
}
ok =(1 << 21)-1;// 2,097,151
f[1][1]=1;
for (int c = 1; c <= ok; c++)
{
for (int i = 1; i <= 21; i++)
{
if (c & (1 << (i - 1)))
for (int j = 1; j <= 21; j++)
{
if (!(c & (1 << (j - 1))) && have[i][j])
f[c | (1 << (j - 1))][j] += f[c][i];
}
}
}
for (int i = 1; i <= 21; i++)
{
ans5 += f[ok][i];
}
cout << ans5 << endl;
}
//==================== answer ====================
signed main()
{
string ans[] = {
"3181", // 双引号中替换为 A 题的答案
"40257", // 双引号中替换为 B 题的答案
"2430", // 双引号中替换为 C 题的答案
"10266837", // 双引号中替换为 D 题的答案
"881012367360", // 双引号中替换为 E 题的答案
};
char T;
cin >> T;
cout << ans[T - 'A'] << endl;
return 0;
}

P8742 [蓝桥杯 2021 省 AB] 砝码称重

题目描述

你有一架天平和 个砝码, 这 个砝码重量依次是 。 请你计算一共可以称出多少种不同的重量?

注意砝码可以放在天平两边。

输入格式

输入的第一行包含一个整数

第二行包含 个整数:

输出格式

输出一个整数代表答案。

输入输出样例 #1

输入 #1

1
2
3
1 4 6

输出 #1

1
10

说明/提示

【样例说明】

能称出的 10 种重量是:

【评测用例规模与约定】

对于 的评测用例,

对于所有评测用例, 个砝码总重不超过

蓝桥杯 2021 第一轮省赛 A 组 F 题(B 组 G 题)。

解法

01背包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int f[101][N];
signed main()
{
int n, w, sum = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &w);
sum += w;
for (int j = sum; j; j--)
if (f[i - 1][j])
f[i][j] = f[i][abs(j - w)] = f[i][j + w] = 1;
f[i][w] = 1;
}
int ans = 0;
for (int j = 1; j <= sum; j++)
ans += f[n][j];
printf("%d\n", ans);
return 0;
}

P8743 [蓝桥杯 2021 省 A] 异或数列

题目描述

Alice 和 Bob 正在玩一个异或数列的游戏。初始时,Alice 和 Bob 分别有一个整数 , 有一个给定的长度为 的公共数列

Alice 和 Bob 轮流操作,Alice 先手,每步可以在以下两种选项中选一种:

选项 1: 从数列中选一个 给 Alice 的数异或上, 或者说令 变为 。(其中 表示按位异或)

选项 2: 从数列中选一个 给 Bob 的数异或上,或者说令 变为

每个数 都只能用一次, 当所有 均被使用后( 轮后)游戏结束。游戏结束时, 拥有的数比较大的一方获胜,如果双方数值相同,即为平手。

现在双方都足够聪明,都采用最优策略,请问谁能获胜?

输入格式

每个评测用例包含多组询问。询问之间彼此独立。

输入的第一行包含一个整数 ,表示询问数。

接下来 行每行包含一组询问。其中第 行的第一个整数 表示数列长度,随后 个整数 表示数列中的每个数。

输出格式

输出 行,依次对应每组询问的答案。

每行包含一个整数 分别表示 Alice 胜、平局或败。

输入输出样例 #1

输入 #1

1
2
3
4
5
4
1 1
1 0
2 2 1
7 992438 1006399 781139 985280 4729 872779 563580

输出 #1

1
2
3
4
1
0
1
1

说明/提示

对于所有评测用例,

蓝桥杯 2021 第一轮省赛 A 组 G 题。

解法

转换成二进制,对于某一位,如果它是1,则反转这一位答案。0对答案无影响。奇数个1异或得1,偶数个1异或得0

  • 当1有偶数个时,偶数=偶数+偶数,这一位平手。
  • 当1有奇数个时,奇数=奇数+偶数,两人都想办法获得奇数个1。
    • 只有一个1,Alice直接选,Alice win
    • 当0有偶数个,两人相抵,Alice win
    • 当0有奇数个,Bob选一个0,反转局面,Bob win

例:1 1 1 0 0 0
Alice:1
Bob:0(反转先手)
Alice:0
Bob:0
Alice:1(被迫)
Bob:Alice 1
Bob win

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <bits/stdc++.h>
using namespace std;
signed main()
{
int t, n, x, cnt[22];
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < n; i++)
{
scanf("%d", &x);
for (int b = 0; x; b++)
{
if (x & 1)
cnt[b]++;
x >>= 1;
}
}
int win = 0;
for (int i = 20; i >= 0; i--)
{
if (cnt[i] & 1)
{
if (cnt[i] == 1)
win = 1;
else
win = n & 1 ? 1 : -1; // 偶数个0Alice win
break;
}
}
printf("%d\n", win);
}
return 0;
}
/*

*/

P8744 [蓝桥杯 2021 省 A] 左孩子右兄弟

题目描述

对于一棵多叉树,我们可以通过“左孩子右兄弟”表示法,将其转化成一棵二叉树。

如果我们认为每个结点的子结点是无序的,那么得到的二叉树可能不唯一。换句话说,每个结点可以选任意子结点作为左孩子,并按任意顺序连接右兄弟。

给定一棵包含 个结点的多叉树,结点从 编号,其中 号结点是根,每个结点的父结点的编号比自己的编号小。请你计算其通过”左孩子右兄弟”表示法转化成的二叉树,高度最高是多少。(只有根结点这一个结点的树高度为

例如如下的多叉树:

可能有以下 种 (这里只列出 种, 并不是全部) 不同的 “左孩子右兄弟” 表示:

其中最后一种高度最高, 为

输入格式

输入的第一行包含一个整数

以下 行, 每行包含一个整数, 依次表示 号结点的父结点编号。

输出格式

输出一个整数表示答案。

输入输出样例 #1

输入 #1

1
2
3
4
5
5
1
1
1
2

输出 #1

1
4

说明/提示

对于 的评测用例,;

对于所有评测用例,

蓝桥杯 2021 第一轮省赛 A 组 H 题。

解法

dfs
最大答案=孩子数+孩子中的最大答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n;
vector<vector<int>> child(N);
int dfs(int u)
{
int ret = 0;
for (int v : child[u])
ret = max(ret, dfs(v));
return ret + child[u].size();
}
signed main()
{
scanf("%d", &n);
int r;
for (int i = 2; i <= n; i++)
{
scanf("%d", &r);
child[r].push_back(i);
}
printf("%d", dfs(1));
return 0;
}


P8745 [蓝桥杯 2021 省 AB] 括号序列

题目描述

给定一个括号序列,要求尽可能少地添加若干括号使得括号序列变得合法,当添加完成后,会产生不同的添加结果,请问有多少种本质不同的添加结果。两个结果是本质不同的是指存在某个位置一个结果是左括号,而另一个是右括号。

例如,对于括号序列 (((),只需要添加两个括号就能让其合法,有以下几种不同的添加结果:()()()()(())(())()(()())((()))

输入格式

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

输出格式

输出一个整数表示答案,答案可能很大,请输出答案除以 (即 )的余数。

输入输出样例 #1

输入 #1

1
((()

输出 #1

1
5

说明/提示

对于 的评测用例,

对于所有评测用例,

蓝桥杯 2021 第一轮省赛 A 组 I 题(B 组 J 题)。

解法

python生成代码

1
2
3
4
5
6
7
8
a=['(',')']
from random import randint
def f():
l=randint(5,12)
for i in range(l):
print(a[randint(0,1)],end='')
print()
f()

嗯。。。后面没有做了(逃)

一雪2024的前耻,今年报销了300大洋报名费!慢慢复盘。

考时黑客不会优化,最后一题只写完了拖布,拓步,托……反正就是那个什么什么排序啦!目前黑客已经优化,最后三题还没复盘。

洛谷评测

注意事项

  • 这里的题解偷懒了,实际上考试时不要用ios::sync_with_stdio(false);cin.tie(nullptr), cout.tie(nullptr);,直接用scanfprintf最保险
  • 注意数据范围,注意用long long或者unsigned long long的情况
  • 一定记得return 0
  • 注意devcpp开栈和c++版本
  • 某些特殊的填空题可以用python写,改天新开一篇博文写
  • 写一题交一题
  • 拿不要死磕一道题,尽可能每道题都暴力骗到分。实在不行直接输出样例。

P12138 [蓝桥杯 2025 省 A] 寻找质数

题目背景

本站蓝桥杯 2025 省赛测试数据均为洛谷自造,与官方数据可能存在差异,仅供学习参考。

题目描述

如果一个正整数只能被 和它本身两个数整除,就称为一个质数。最小的几个质数依次是

请问,第 个质数是多少?

输入格式

输出格式

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

解法

get 5/5分
暴力就好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int cnt = 1, n = 1;
while (cnt < 2025)
{
n += 2;
bool prime = true;
for (int i = 3; i < n; i += 2)
{
if (n % i == 0)
{
prime = false;
break;
}
}
if (prime)
{
++cnt;
}
}
cout << n << endl;

P12139 [蓝桥杯 2025 省 A] 黑白棋

题目描述

小蓝最近迷上了一款名为“黑白棋填充”的游戏。该游戏在一个方形网格棋盘上进行,其中部分格子已经填有黑色或白色的棋子,而其他格子为空,等待玩家填入棋子。

游戏规则是,玩家需要按照以下规则填满整个棋盘,才能算作胜利:

  1. 黑白棋子数量均等
    在每一行和每一列中,黑色棋子和白色棋子的数量必须相等。
  2. 相邻棋子限制
    在棋盘的任何一行或一列中,不能有超过两个相同颜色的棋子连续排列(即不允许出现“黑黑黑”或“白白白”的情况)。
  3. 行列唯一性
    每一行的棋子排列方式必须是唯一的,不能与棋盘中的任何其他行完全相同。
    每一列的棋子排列方式必须是唯一的,不能与棋盘中的任何其他列完全相同。
    行与列之间的棋子排列不作比较,即行可以与列相同,无需满足行列间的唯一性。

现在有一个 的棋盘,如上图所示,其中部分格子已填入棋子(黑色或白色),其余格子需要你填充,题目保证有唯一解。

请给出唯一的正确解,并按照以下格式输出答案:

  • 黑色棋子用 表示,白色棋子用 表示。
  • 从左到右、从上到下的顺序,依次遍历棋盘上的所有格子,并将这些值拼接成一个长度为 的字符串。

例如,假设最终填充完成后的棋盘如下(仅为示例,并非真实答案):

1
2
3
4
5
6
1 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
0 0 1 1 0 0
0 0 1 1 1 1

则输出结果应为:100000000000000000001000001100001111

输入格式

输出格式

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

解法

get 5/5分
考试时第一反应是打excel表格,好吧。其实dfs稍微剪枝一下就可以。狠狠暴力!忘情地暴力!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
int board[][6] = {
{1, 0, 2, 0, 2, 2},
{2, 2, 2, 0, 2, 2},
{2, 2, 2, 2, 0, 0},
{2, 2, 2, 2, 2, 2},
{2, 2, 1, 2, 2, 1},
{2, 0, 2, 2, 1, 2}};
// 颜色,对应剩余棋子数
int row[2][6] = {{3, 3, 3, 3, 3, 3}, {3, 3, 3, 3, 3, 3}},
col[2][6] = {{3, 3, 3, 3, 3, 3}, {3, 3, 3, 3, 3, 3}};
void dfs(int r, int c)
{
if (r == 5) // 列尾
{
//每一列的棋子排列方式必须是唯一的,不能与棋盘中的任何其他列完全相同。
for (int j = 0; j < c - 1; ++j)
{
bool ok = false;
for (int i = 0; i < 6; ++i)
{
if (board[i][j] != board[i][c - 1])
{
ok = true;
break;
}
}
if (!ok)
return;
}
}
if (c == 6) // 行尾
{
// 每一行的棋子排列方式必须是唯一的,不能与棋盘中的任何其他行完全相同。
for (int i = 0; i < r; ++i)
{
bool ok = false;
for (int j = 0; j < 6; ++j)
{
if (board[i][j] != board[r][j])
{
ok = true;
break;
}
}
if (!ok)
return;
}
++r;
c = 0;
}
if (r == 6) // 列尾
{
for (int i = 0; i < 6; ++i)
{
for (int j = 0; j < 6; ++j)
{
cout << board[i][j];
}
// cout << endl;
}
exit(0);
}
// 该位置为空
if (board[r][c] == 2)
{
for (int color = 0; color < 2; color++)
{
// 每一行和每一列中,黑色棋子和白色棋子的数量必须相等
if (row[color][r] <= 0 || col[color][c] <= 0)
continue;
// 在棋盘的任何一行或一列中,不能有超过两个相同颜色的棋子连续排列(即不允许出现“黑黑黑”或“白白白”的情况)。
if (r >= 2 && color == board[r - 1][c] && color == board[r - 2][c])
continue;
if (c >= 2 && color == board[r][c - 1] && color == board[r][c - 2])
continue;
--row[color][r];
--col[color][c];
board[r][c] = color;
dfs(r, c + 1);
++row[color][r];
++col[color][c];
}
board[r][c] = 2;
}
else // 该位置已经有棋子
{
int color = board[r][c];
// 每一行和每一列中,黑色棋子和白色棋子的数量必须相等
if (row[color][r] <= 0 || col[color][c] <= 0)
return;
// 在棋盘的任何一行或一列中,不能有超过两个相同颜色的棋子连续排列(即不允许出现“黑黑黑”或“白白白”的情况)。
if (r >= 2 && color == board[r - 1][c] && color == board[r - 2][c])
return;
if (c >= 2 && color == board[r][c - 1] && color == board[r][c - 2])
return;
--row[color][r];
--col[color][c];
dfs(r, c + 1);
++row[color][r];
++col[color][c];
}
}
signed main()
{
dfs(0, 0);//101001010011101100010110011001100110
return 0;
}

P12140 [蓝桥杯 2025 省 A] 抽奖

题目背景

本站蓝桥杯 2025 省赛测试数据均为洛谷自造,与官方数据可能存在差异,仅供学习参考。

题目描述

LQ 商场为了回馈广大用户,为在此消费的用户提供了抽奖机会:抽奖机有三个转轮,每个转轮上都分布有 个数字图案,标号为 ,按照从 顺序转动,当转到第 个图案时会从第一个继续开始。奖项如下:

  1. 三个相同的图案,积分
  2. 两个相同的图案,积分
  3. 三个数字图案,从左到右连续(例如 ),积分
  4. 三个数字图案,经过顺序调整后连续(例如 ),积分

抽奖机处于初始状态,三个转轮都处于第一个位置。每次开始抽奖,都会产生三个对应的随机数 ,表示第 个转轮会向后转动 次停下。下次抽奖时,转轮会从上一次转动后的位置开始继续转动。

注意,一次抽奖最多只能获得一次积分,如果同时命中多个奖项,以积分最大的那个奖项为准。

请问,如果执行 次抽奖,总积分值是多少?

输入格式

输入的第一行包含一个正整数 ,表示转轮大小。

第二行包含 个正整数 ,依次表示第一个转轮上的数字图案,相邻整数之间使用一个空格分隔。

第三行包含 个正整数 ,依次表示第二个转轮上的数字图案,相邻整数之间使用一个空格分隔。

第四行包含 个正整数 ,依次表示第三个转轮上的数字图案,相邻整数之间使用一个空格分隔。

第五行包含一个整数 ,表示抽奖次数。

接下来 行,每行包含三个正整数 ,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示答案,即 次抽奖累计获得的积分的值。

输入输出样例 #1

输入 #1

1
2
3
4
5
6
7
8
4
3 2 4 1
2 2 2 2
4 3 0 9
3
4 4 4
3 1 1
40 39 2

输出 #1

1
300

说明/提示

样例说明

  • 第一次抽奖:三个转轮都转动 次,到达位置 ,数字图案为 ,积分
  • 第二次抽奖:数字图案为 ,积分
  • 第三次抽奖:数字图案为 ,积分不增加。

评测用例规模与约定

  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于所有评测用例,

解法

大模拟,暴力。注意转盘用%运算模拟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <bits/stdc++.h>
using namespace std;
#define N 1005

int n, m, d, res = 0;
int arr[3][N];
int pos[3], jiang[3];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);

cin >> n;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < n; ++j)
cin >> arr[i][j];
cin >> m;
while (m--)
{
for (int i = 0; i < 3; ++i)
{
cin >> d;
pos[i] = (pos[i] + d) % n;
jiang[i] = arr[i][pos[i]];
}
if (jiang[0] == jiang[1])
{
if (jiang[0] == jiang[2])
res += 200;
else
res += 100;
}
else if (jiang[0] == jiang[2] || jiang[1] == jiang[2])
{
res += 100;
}
else if (jiang[0] + 1 == jiang[1] && jiang[0] + 2 == jiang[2])
{
res += 200;
}
else
{
sort(jiang, jiang + 3);
if (jiang[0] + 1 == jiang[1] && jiang[0] + 2 == jiang[2])
{
res += 100;
}
}
}
cout << res << endl;
return 0;
}

P12141 [蓝桥杯 2025 省 A] 红黑树

题目描述

小蓝最近学习了红黑树,红黑树是一种特殊的二叉树,树上的结点有两种类型:红色结点和黑色结点。

小蓝在脑海中构造出一棵红黑树,构造方式如下:

  1. 根结点是一个红色结点;
  2. 如果当前结点 是红色结点,那么左子结点 是红色结点,右子结点 是黑色结点;
  3. 如果当前结点 是黑色结点,那么左子结点 是黑色结点,右子结点 是红色结点;

此二叉树前几层的形态如下图所示:

小蓝会从树上随机挑选结点,请你帮忙判断他选出的是红色结点还是黑色结点。

输入格式

输入的第一行包含一个正整数 ,表示小蓝挑选的结点数。

接下来 行,每行包含两个正整数 ,用一个空格分隔,表示小蓝挑选的结点是第 行(从上往下数)第 个(从左往右数)结点。

输出格式

输出 行,每行包含一个字符串,依次表示小蓝每次挑选的结点的答案。RED 表示红色结点,BLACK 表示黑色结点。

输入输出样例 #1

输入 #1

1
2
3
2
1 1
2 2

输出 #1

1
2
RED
BLACK

说明/提示

样例说明

  • 第一行第一个结点为根结点,红色;
  • 第二行第二个结点为黑色结点。

评测用例规模与约定

  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于所有评测用例,

解法

get 10/10
使用瞪眼法,一眼顶针,红黑树看出是异或运算,多往下画两行就发现,颜色和行数无关。把红和黑分别看作0和1,颜色就是异或1的运算。
红黑树示意图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int n, m, k;
cin >> m;
while (m--)
{
cin >> n >> k;
int a = 0;
--k;
while (k)
{
a ^= (k & 1);
k >>= 1;
}
if (a)
cout << "BLACK" << endl;
else
cout << "RED" << endl;
}

P12142 [蓝桥杯 2025 省 A] 黑客

题目描述

小蓝正在两台电脑之间拷贝数据,数据是一个 大小的正整数矩阵,因此总共有 个由空格分开的整数,其中前两个整数分别为 。然而,有黑客入侵了小蓝的电脑,导致这 个正整数的顺序被打乱了。小蓝想知道最多可能有多少个不同的原矩阵。

两个矩阵相同当且仅当它们行数相同、列数相同,且每个位置上的数相同。

输入格式

输入的第一行包含一个正整数

第二行包含 个正整数 ,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示答案。答案可能很大,请输出答案除以 的余数。

输入输出样例 #1

输入 #1

1
2
6
2 2 1 4 3 3

输出 #1

1
24

说明/提示

样例说明

可能的原矩阵情况包括:

  1. :有 种原矩阵:
  2. :有 种原矩阵;
  3. :有 种原矩阵;

总计 种。

评测用例规模与约定

  • 对于 的评测用例,
  • 对于所有评测用例,

解法

思路

不用管是不是二维矩阵,直接看作一维数矩阵。题目大意:当找到两个数 ,当 时,求剩余 个数有多少种不重复的排列,并对其求和。

考试时不知道带模的除法怎么做,只好开了 unsigned long long 并且打了个 22 以内的阶乘表,大概是拿 40% 的分了。

实际上,后面补习数论,模意义下的除法是这样的:

其中 是求 模意义下的逆元。这里数据量不大,可以套快速幂公式。

而这里的排列公式为:当有 个不相同的数 排列,对于每一个数 ,它的数量是 ,排列方式有 种。

豪!基础复习完毕。回到题目——

对于行数 和列数 ,当 时,求剩余 个数的排列方式数目。排列公式分母里要去掉一个 和一个 ,当两者相同时,就相当于去掉两个

对于一对“行数”和“列数”,上述排列公式的分母如下:

将分母带入排列公式:

最终答案表达式,即求和:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <bits/stdc++.h>
using namespace std;
#define ll unsigned long long
#define N 500005
const int p = 1000000007;

int n, m;
unordered_map<ll, int> mp;//对每个数,对应的数量。unordered_map比map更高效
ll jc[N]; // 阶乘
ll inverse(ll a)//快速幂逆元
{
ll b = p - 2, ret = 1;
while (b)
{
if (b & 1)
ret = ret * a % p;
a = a * a % p;
b >>= 1;
}
return ret;
}
signed main()
{
jc[0] = jc[1] = 1;
for (int i = 2; i < N; ++i)
{
jc[i] = jc[i - 1] * i % p;
}
scanf("%d", &n);
m = n - 2;//矩阵的大小
ll a, b = 1, rc = 0;
for (int i = 0; i < n; ++i)
{
scanf("%lld", &a);
++mp[a];
}
for (auto i : mp)
{
b = b * jc[i.second] % p;
}
for (auto r : mp)
{
if (m % r.first != 0)
continue;
auto c = mp.find(m / r.first);
if (c == mp.end()) // 找不到两数相乘为n-2
continue;
if (r.first != c->first)
rc = (rc + r.second * c->second % p) % p;
else
rc = (rc + r.second * (r.second - 1) % p) % p;
}
cout << jc[n - 2] * inverse(b) % p * rc % p << endl;
return 0;
}

P12143 [蓝桥杯 2025 省 A] 好串的数目

题目描述

对于一个长度为 的字符串 来说,子串的定义是从中选出两个下标 ,这之间所有的字符组合起来的一个新的字符串: 就是其中一个子串。

现在给出一个只有数字字符 组成的数字字符串,小蓝想要知道在其所有的子串中,有多少个子串是好串。一个子串是好串,当且仅当它满足以下两个条件之一:

  1. 单字符子串一定是好串,即当子串长度为 时,它总是好串;
  2. 长度大于 时,可以拆分为两个连续非递减子串
    一个串 连续非递减子串是指,对于所有 ,满足 。即数字串中的每一个数字,要么等于上一个数字,要么等于上一个数字加 。例如 12233456 是连续非递减子串。

输入格式

输入一行包含一个字符串

输出格式

输出一行包含一个整数表示答案,即好串的数目。

输入输出样例 #1

输入 #1

1
12258

输出 #1

1
12

输入输出样例 #2

输入 #2

1
97856

输出 #2

1
13

说明/提示

样例说明 1

  • 长度为 的好串:12258,共 个;
  • 长度为 的好串:12222558,共 个;
  • 长度为 的好串:122225,共 个;
  • 长度为 的好串:1225,共 个;

总计 个。

样例说明 2

  • 长度为 的好串:97856,共 个;
  • 长度为 的好串:97788556,共 个;
  • 长度为 的好串:978785856,共 个;
  • 长度为 的好串:7856,共 个;

总计 个。

评测用例规模与约定

  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于 的评测用例,
  • 对于所有评测用例, 中只包含数字字符

解法

找规律

P12144 [蓝桥杯 2025 省 A] 地雷阵

题目描述

小蓝正在平面直角坐标系中的第一象限里玩一个逃生小游戏。在第一象限中埋有 颗地雷,第 颗地雷的坐标为 ,触发范围为以 为圆心,半径为 的圆。一旦小蓝走进了圆内就会触发地雷导致游戏失败。小蓝初始在原点 上,他需要在第一象限内选择一个方向一直往前走,如果能不触发任何地雷即可成功通关游戏。他想知道在 中均匀随机选择一个方向,即在 (朝向 轴正方向)至 (朝向 轴正方向)之间随机选择一个方向,通关游戏的概率是多少?

输入格式

输入的第一行包含一个正整数

接下来 行,每行包含三个正整数 ,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含一个实数,四舍五入保留三位小数,表示答案。

输入输出样例 #1

输入 #1

1
2
1
2 2 1

输出 #1

1
0.540

输入输出样例 #2

输入 #2

1
2
3
2
1 3 1
3 1 1

输出 #2

1
0.181

说明/提示

评测用例规模与约定

  • 对于 的评测用例,
  • 对于所有评测用例,

解法

根据圆形切线的性质,每一个圆都可以对应一个角度范围。对角度范围进行排序,就是一个线段覆盖的贪心问题。

碎碎念 注意反三角函数在C++里是atan,还有他是弧度还是角度?π 以及它的各个倍数在C++里也是有现成的值,好像是什么M_PI?我当时直接跑到文件夹里搜索的()而且应该是有弧度角度转换的函数吧

P12145 [蓝桥杯 2025 省 A] 扫地机器人

题目描述

在一个含有 个点 条边的无重边无自环的连通无向图中,有一个扫地机器人在执行清扫作业。其中结点 的标记 :如果为 ,则说明该结点需要进行清扫,扫地机器人在到达这个结点时会顺便进行清扫工作。机器人想知道,如果选定任意结点出发,每条边只能经过一次的话,最多能清扫多少个待清扫结点?

输入格式

输入的第一行包含一个正整数

第二行包含 个整数 ,相邻整数之间使用一个空格分隔。

接下来 行,每行包含两个正整数 ,用一个空格分隔,表示结点 和结点 之间有一条边。

输出格式

输出一行包含一个整数表示答案。

输入输出样例 #1

输入 #1

1
2
3
4
5
6
7
8
9
10
11
9
1 0 1 0 0 1 1 0 1
2 8
2 9
2 5
1 5
1 3
1 4
4 5
4 6
6 7

输出 #1

1
4

说明/提示

样例说明

其中一种可行路线:,清扫结点 (共 个)。

评测用例规模与约定

  • 对于 的评测用例,
  • 对于所有评测用例,

解法

一眼顶针,题目里的图为 个结点和 条边的连通图。当有 个结点和 条边的连通图,这是一颗树,树再加上一条边,就是只有一个环的图。除了一个环,剩下都是树的图,即基环树

题意:一个基环树,每个点的权值为0或1,选择一条链,点不能走重复,权值总和最大。

那么,我们的最佳路线,有可能有三种:

  1. 从叶子结点出发,到某一个祖先,再跑到另一个叶子结点
  2. 从叶子结点出发,走到环绕到另一个分岔路口,再走到另一个叶子结点;
  3. 同样从叶子结点出发,走到环跑一圈;或者根本没有叶子结点,直接跑一圈。
    基环树
    这时候可以从叶子结点开始拓补排序,得到从这个环结点进出环的点权值之和。
    考试的时候就只写完了拓补排序,还没有跑环就到时间了。最后一题也算了。

网上的教程,包括官方的教程不太适用,自己摸索了一遍

下载安装驱动

有两种芯片,看你的小芯片上写的是CP2102还是CH340G👀(两个小按键之间),选择不同的驱动。

CP2102芯片

CP2102驱动下载地址:
https://www.silabs.com/developer-tools/usb-to-uart-bridge-vcp-drivers?tab=downloads
选择CP210x Windows Drivers下载,解压。
图片
然后安装。
笔记本电脑选:CP210xVCPInstaller_x64.exe
台式电脑(诶?)选:CP210xVCPInstaller_x86.exe

CH340G芯片

驱动下载地址:
https://www.arduined.eu/ch340-windows-10-driver-download/
点击蓝字CH340 driver for Windows 10下载,解压。点SETUP.EXE安装。

Tips

如果你没有放大镜,看不清楚的话,你也可以两个都装,因为非常好装。

连接设备

长按Esp板子上的boot按键,同时插上电脑,并抬起按键。
同时按下组合键:“Win + R”,打开“运行”对话框,在其中输入“devmgmt.msc”,点击“确定”即可打开“设备管理器”。点开端口。应该能看到包含芯片名称的一个端口,如图
图片
如果没有的话,首先不要怀疑驱动,建议你先多换几个USB线,我换了三根三根。。。
然后记住是COM几,我的是COM4,下面的步骤记得替换。

下载固件

最新固件网址:
https://micropython.org/download/ESP8266_GENERIC/
直接找到
Firmware
Releases
初学者下载最上方的bin文件即可(带latest标识)。本人下载的时候版本是v1.24.1 (2024-11-29) .bin
图片

下载python

确保已安装Python 3.7或更高版本。虽然官网说, Python 2.7和Python 3.4以上都可以,但是你也不希望被同学知道你还在用老版本的Python吧(不是)。

Python官网:https://www.python.org/

用pip安装esptool

首先你有可能要更新pip。

1
python.exe -m pip install --upgrade pip

接着

1
pip install esptool

找到你Python的Scripts文件夹(里面应该有个esptool.exe),加上记住它的路径。再在后面加上esptool

找到esptool的一种方式
cmd怎么打开 win+R打开运行,输入cmd,回车

在cmd,或者Vscode bash或者Pycharm bash或者powershell或者别的里,输入

1
pip --version

我这里显示了

1
pip 25.0.1 from D:\GitHub\Smart-Aquaculture-esp8266\.venv\lib\site-packages\pip (python 3.10)

看到这个D:\GitHub\Smart-Aquaculture-esp8266\.venv\lib\site-packages\pip,去掉lib\site-packages\pip,换成Scripts\esptool,即D:\GitHub\Smart-Aquaculture-esp8266\.venv\Scripts\esptool。等会儿要用。

</details>

下面的.venv/Scripts/esptool替换成你的路径
因为我建了虚拟环境,就用相对路径了,所以后面就用.venv/Scripts/esptool简化写了。

对于以下两个命令,你需要更改三个地方:

  1. .venv/Scripts/esptool改成你在用pip安装esptool一步找到esptool的路径。
  2. COM4改成在连接设备一步找到的COM几
  3. D:\software\ESP8266_GENERIC-20241129-v1.24.1.bin改成你在下载固件一步下载的固件的路径。

打开cmd,先擦除闪存

1
.venv/Scripts/esptool --port COM4 erase_flash

然后烧录固件
1
.venv/Scripts/esptool --port COM4  --baud 460800 write_flash --flash_size=detect 0  D:\software\ESP8266_GENERIC-20241129-v1.24.1.bin

下载安装ide

推荐thonny。
下载地址:https://thonny.org/
虽然这个软件某不可言说的方面有点抽象,但是是确实好用。也可以选择别的ide。

如图:
图片

图片

Hello world!

成功打开之后,Ctrl+N新建main.py文件,到了喜闻乐见的Hello world环节

1
print("hello world!")

F5运行,看看能不能hello world。

Blink!

图片

参考网址:
https://docs.micropython.org/en/latest/esp8266/tutorial/intro.html

0%