跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

蓝桥杯算法竞赛经典题解汇总

汇总了蓝桥杯算法竞赛中的九道经典题目,涵盖 C++ 语言实现。内容涉及前缀和与同余定理(K 倍区间)、二分查找(分巧克力)、动态规划与记忆化搜索(密码脱落)、模拟(冰雹数、饮料换购)、字符串处理(密文搜索、音节判断)、图论最小生成树(通电)及深度优先搜索(全球变暖)。文章提供了完整代码示例及关键逻辑解析,修正了部分原始代码逻辑错误,适合算法初学者复习与练习。

FlinkHero发布于 2026/3/27更新于 2026/9/1177 浏览
蓝桥杯算法竞赛经典题解汇总

蓝桥杯 97 K 倍区间【难】

题目链接:https://www.lanqiao.cn/problems/97/learning/

#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int main() {
    int n, k;
    cin >> n >> k;
    ll cnt[N] = {1}; // cnt[r]:前缀和余数为 r 的出现次数,初始 cnt[0]=1
    ll sum = 0, ans = 0; // sum 当前前缀和
    for (int i = 0; i < n; ++i) {
        int num;
        cin >> num;
        sum += num;
        int r = sum % k;
        cnt[r]++;
    }
    for (int i = 0; i < k; ++i) {
        ans += cnt[i] * (cnt[i] - 1) / 2;
    }
    cout << ans << endl;
    return 0;
}

如果两个前缀和除以 k 的余数相同,那么它们对应的区间和就是 k 的倍数。所以我们不需要关心具体的区间,只需要统计相同余数的前缀和出现了多少次,就能算出有多少个符合条件的区间。

蓝桥杯 99 分巧克力

题目链接:https://www.lanqiao.cn/problems/99/learning/

#include <iostream>
using namespace std;
  N =  + ;
 h[N], w[N];
 n, k;
{
      sum = ; 
    ( i = ; i < n; ++i) {
        sum += ( * h[i]/mid) * (w[i]/mid);
        (sum >= k)  ;
    }
     ;
}
{
    ios::();
    cin.();
    cin >> n >> k;
    ( i = ; i < n; ++i) {
        cin >> h[i] >> w[i];
    }
     l = , r = ;
    (l < r) {
         mid = (l + r + ) / ;
        ((mid)) l = mid;
         r = mid - ;
    }
    cout << l << ;
     ;
}
const
int
1e5
10
int
int
bool check(int mid)
long
long
0
// 统计总共能切多少块
for
int
0
1LL
if
return
true
return
false
int main()
sync_with_stdio
false
tie
nullptr
for
int
0
int
1
1e5
while
int
1
2
if
check
else
1
'\n'
return
0

关于二分查找边界:

  • (l + r + 1) / 2:找最大值(最后一个满足条件的)需要加 1,偏向右边。
  • check 函数作用:检查如果正方形的边长是 mid,能不能从所有巧克力中切出至少 k 块。

蓝桥杯 124 密码脱落

题目链接:https://www.lanqiao.cn/problems/124/learning/

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1005;
char s[N];
int memo[N][N]; // 初始化为 -1
// 最长回文子序列
int dfs(int i, int j){
    if(memo[i][j] != -1) return memo[i][j];
    if(i == j) return memo[i][j] = 1;
    if(i > j) return memo[i][j] = 0;
    if(s[i] == s[j]) memo[i][j] = dfs(i+1, j-1) + 2;
    else memo[i][j] = max(dfs(i+1, j), dfs(i, j-1));
    return memo[i][j];
}
int main(){
    cin >> s;
    int n = strlen(s);
    memset(memo, -1, sizeof(memo));
    int max_pal = dfs(0, n-1);
    cout << n - max_pal << '\n';
    return 0;
}

题目大意:给一个字符串 s,问最少需要'脱落'多少个字符(即删除多少个字符),才能让剩下的字符构成一个回文串。

转化思路:最少删除字符数 = 字符串长度 - 最长回文子序列(LPS)的长度。

递归逻辑:

  • 若 s[i] == s[j],则 LPS(i, j) = LPS(i+1, j-1) + 2。
  • 若 s[i] != s[j],则 LPS(i, j) = max(LPS(i+1, j), LPS(i, j-1))。

注意:memo[i][j] 表示字符串从位置 i 到位置 j 的最长回文子序列长度,需初始化为 -1。

蓝桥杯 128 冰雹数

题目链接:https://www.lanqiao.cn/problems/128/learning/

#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
bool vis[N];
int main() {
    ll n, max_h = 0;
    cin >> n;
    for(ll i = 1; i < n; ++i) {
        if(vis[i]) continue;
        ll x = i;
        while(x != 1) {
            if(x <= n) vis[x] = true;
            max_h = max(max_h, x);
            if(x % 2 == 0) x /= 2;
            else x = x * 3 + 1;
        }
    }
    cout << max_h << endl;
    return 0;
}

蓝桥杯 138 密文搜索

题目链接:https://www.lanqiao.cn/problems/138/learning/

#include <iostream>
#include <string>
#include <algorithm>
#include <unordered_map>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    string s;
    int n, ans = 0;
    cin >> s >> n;
    unordered_map<string, int> cnt; // 密码存放在哈希表中
    for(int i = 0; i < n; ++i) {
        string pwd;
        cin >> pwd;
        sort(pwd.begin(), pwd.end());
        cnt[pwd]++;
    }
    int len = s.size();
    for(int i = 0; i <= len - 8; ++i) {
        string sub = s.substr(i, 8); // 把 s 中的字串排序好再插哈希表存放的密码里面有没有
        sort(sub.begin(), sub.end());
        ans += cnt[sub];
    }
    cout << ans << endl;
    return 0;
}

蓝桥杯 143 饮料换购

题目链接:https://www.lanqiao.cn/problems/143/learning/

#include <iostream>
using namespace std;
int main() {
    int n, yu = 0, count;
    cin >> n;
    count = n;
    while(n >= 3) {
        yu = n % 3; // 多余的未能兑换的瓶子瓶盖 该瓶子包含在 count 中
        n = n / 3; // 瓶盖兑换的瓶子数量
        count += n;
        n += yu; // 新增的瓶子瓶盖加上未能兑换的瓶子瓶盖
    }
    cout << count;
    return 0;
}

蓝桥杯 146 三元组中心问题

题目链接:https://www.lanqiao.cn/problems/146/learning/

#include <iostream>
using namespace std;
int main() {
    int n, ans = 0;
    cin >> n;
    int a[1010];
    bool is_center[1010] = {false};
    for(int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    for(int j = 1; j < n - 1; ++j) {
        for(int i = 0; i < j; ++ i) {
            for(int k = j + 1; k < n; ++k) {
                if(a[i] < a[j] && a[j] < a[k]) {
                    is_center[j] = true;
                    break;
                }
            }
            if (is_center[j]) break;
        }
    }
    for(int j = 0; j < n; ++j) {
        if (is_center[j]) ans++;
    }
    cout << ans << '\n';
}

定义:一个元素 a[j] 被称为'中心',需要满足存在 i < j 且 a[i] < a[j],以及存在 k > j 且 a[j] < a[k]。即 a[j] 左边至少有一个比它小的数,右边至少有一个比它大的数。

蓝桥杯 148 音节判断

题目链接:https://www.lanqiao.cn/problems/148/learning/

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s;
    cin >> s;
    bool judge = 0; // 0 表示辅音 1 表示元音
    int ans = 0;
    for (int i = 0; i < s.length(); ++i) {
        if ((s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') && judge == 1) {
            ans++;
            judge = 0;
        }else if (s[i] != 'a' && s[i] != 'e' && s[i] != 'i' && s[i] != 'o' && s[i] != 'u' && judge == 0) {
            ans++;
            judge = 1;
        }
    }
    if (ans == 4) {
        cout << "yes" << endl;
    }else {
        cout << "no" << endl;
    }
    return 0;
}

蓝桥杯 162 通电

题目链接:https://www.lanqiao.cn/problems/162/learning/

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1010;
struct Village {
    int x, y, h;
} v[N];
double calc_cost(int i, int j) {
    int dx = v[i].x - v[j].x;
    int dy = v[i].y - v[j].y;
    int dh = v[i].h - v[j].h;
    return sqrt(dx*dx + dy*dy) + (double)dh*dh;
}
int main() {
    int n;
    cin >> n;
    for(int i = 0; i < n; ++i) {
        cin >> v[i].x >> v[i].y >> v[i].h;
    }
    double dist[N];
    bool vis[N] = {false};
    fill(dist, dist + n, 1e18);
    dist[0] = 0; // 初始化 1 号村庄(下标 0)为起点 距离 0
    double ans = 0;
    for(int i = 0; i < n; ++i) {
        int u = -1;
        double min_d = 1e18;
        for(int j = 0; j < n; ++j) {
            if(!vis[j] && dist[j] < min_d) {
                min_d = dist[j];
                u = j;
            }
        }
        vis[u] = true;
        ans += min_d;
        for (int j = 0; j < n; ++j) {
            if (!vis[j]) {
                double cost = calc_cost(u, j);
                if (cost < dist[j]) dist[j] = cost;
            }
        }
    }
    printf("%.2lf\n", ans);
    return 0;
}

蓝桥杯 178 全球变暖

题目链接:https://www.lanqiao.cn/problems/178/learning/

#include <iostream>
#include <cstring>
using namespace std;
const int N = 1010;
char g[N][N];
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
bool has_safe;
void dfs(int x, int y) {
    if(x < 0 || x >=N || y < 0 || y >= N || g[x][y]!= '#') return;
    g[x][y] = '*'; // 标记当前点为已遍历
    bool is_safe = true;
    for(int i = 0; i < 4; ++i) {
        int nx = x + dx[i], ny = y + dy[i];
        if(g[nx][ny] == '.') { is_safe = false; break; }
    }
    if(is_safe) has_safe = true;
    for(int i = 0; i < 4; ++i){
        dfs(x + dx[i], y + dy[i]);
    }
}
int main() {
    int n, ans = 0;
    cin >> n;
    for(int i = 0; i < n; ++i) cin >> g[i];
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < n; ++j) {
            if(g[i][j] == '#') {
                has_safe = false;
                dfs(i, j);
                if(!has_safe) ans++;
            }
        }
    }
    cout << ans << '\n';
    return 0;
}

遇到一个 #,就开始 DFS,把整个岛屿的 # 改成 *(标记已访问)。在 DFS 过程中,每到一个 #,就检查它是不是安全陆地。只要岛屿上至少有一个安全陆地,这个岛屿就不会被完全淹没。

目录

  1. 蓝桥杯 97 K 倍区间【难】
  2. 蓝桥杯 99 分巧克力
  3. 蓝桥杯 124 密码脱落
  4. 蓝桥杯 128 冰雹数
  5. 蓝桥杯 138 密文搜索
  6. 蓝桥杯 143 饮料换购
  7. 蓝桥杯 146 三元组中心问题
  8. 蓝桥杯 148 音节判断
  9. 蓝桥杯 162 通电
  10. 蓝桥杯 178 全球变暖

更多推荐文章

查看全部
  • 免费 Trae 编辑器体验:i18n 任务排队与模型调度机制分析
  • 构建 AI 临床副驾驶:基于 Go 的电子病历智能助手与 HIS 对接实战(下)
  • 通达信 API 与 Python 构建量化交易系统实战
  • 基于 Python 的商品销售数据分析与可视化
  • Vue 3 组件中实现搜索过滤功能
  • Mac 系统安装与配置 Claude Code 命令行工具
  • C++ 移动语义与右值引用详解
  • DSPy 实战:自动化 Prompt 框架快速入门
  • 网络安全入门教程:从基础理论到渗透测试实战
  • VS Code 中切换或退出 GitHub Copilot 账号的方法
  • 开源 IPTV 播放器 IPTVnator 功能与使用指南
  • 自然语言处理在社交媒体分析中的应用与实战
  • 前端实现视频画中画功能:主窗口与小窗同步控制
  • Vue Print Designer 前端可视化打印设计器详解
  • OpenClaw 架构设计解析:从 Gateway 到 Agent Runtime 全链路
  • 学习大语言模型原理必看的 10 篇论文
  • 链表两两交换的常见写法
  • Windows 下安装与配置 Git 完整指南
  • AIGC 在日常生活中的应用与挑战
  • Flutter 三方库 shelf_web_socket 的鸿蒙化适配指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online