第十六屆藍橋杯軟件賽 C 組省賽 C++ 題解

大家好,今天是 2025 年 9?月 11 日,我來給大家寫一篇關于第十六屆藍橋杯軟件賽 C 組省賽的C++ 題解,希望對大家有所幫助!!!

創作不易,別忘了一鍵三連

題目一:數位倍數

題目鏈接:數位倍數

【題目描述】

【算法原理】

簽到題、枚舉、數位拆分

只需要暴力枚舉 1 到 202504 之間的所有整數,對于每一個整數,拆分它的每一位求和之后看看是不是 5 的倍數就可以了。

至于如何拆分一個整數的每一位,相信大家已經掌握的非常熟練了,直接來看代碼。

【代碼實現】

#include <iostream>using namespace std;bool check(int x)
{int sum = 0; // 統計每一個數的數位和while(x){sum += x % 10;x /= 10;}return sum % 5 == 0;
}int main()
{int cnt = 0;for(int i = 1; i <= 202504; i++)if(check(i))cnt++;cout << cnt << endl; return 0;
} 

題目二:2025

題目鏈接:2025

【題目描述】

【算法原理】

簽到題、枚舉、數位拆分

和題目一類似,只需要暴力枚舉 1 到 20250412 之間的所有整數,對于每一個整數,拆分它的每一位并統計,之后看看是不是含有至少 1 個 0,2 個 2,1 個 5 就可以了。

至于如何拆分一個整數的每一位,相信大家已經掌握的非常熟練了,直接來看代碼。

【代碼實現】

#include <iostream>
#include <cstring>using namespace std;int cnt[10]; // cnt[i] 表示 i 這個數字出現了多少次bool check(int x)
{memset(cnt, 0, sizeof cnt);while(x){cnt[x % 10]++;x /= 10;}if(cnt[0] < 1 || cnt[2] < 2 || cnt[5] < 1) return false; return true;
}int main()
{int c = 0;for(int i = 1; i <= 20250412; i++)if(check(i))c++;cout << c << endl; return 0;
}

題目三:2025圖形

題目鏈接:2025圖形

【題目描述】

【算法原理】

簽到題、模擬、取模運算

找規律 + 周期問題

這道題數據范圍很小,我們完全可以首先構造出一個含有 200 個 “2025” 的字符串,然后針對每一行從不同的位置開始輸出 w 個字符就可以了。(代碼可以自己嘗試實現)

但是,這樣玩的話就沒有什么意思了。我們能不能只存一個 “2025” 呢?

我們寫幾行找一找規律:

遇到周期問題,我們就要首先想到取模操作。

不難發現,這道題輸出位置的值的下標就是橫坐標的值和縱坐標的值之和再模四。

因此,這道題的規律我們就找到了,直接來看代碼:

【代碼實現】

#include <iostream>using namespace std;int a[4] = {2, 0, 2, 5};int main()
{int h, w; cin >> h >> w;for(int i = 0; i < h; i++){for(int j = 0; j < w; j++){cout << a[(i + j) % 4];} cout << endl;}return 0;
} 

題目四:最短距離

題目鏈接:最短距離

【題目描述】

【算法原理】

貪心

這道題目一定不要一直拘泥于題目中的那一幅圖當中,我們拋開坐標系不談,其實這道題目就是讓兩個數組中的值一一對應,使得每一組差的絕對值之和最小:

(我當時就盯著題目中的那幅圖在坐標系中想了很長時間)

我們很容易想到一個貪心策略,就是將兩個數組排序之后,然后按照從小到大的順序一一對應就可以了。

大家如果之前接觸過這一類貪心問題的話,貪心策略是很好想出來的。但是如果之前沒接觸過這樣的問題,就把這個貪心策略當成一個經驗積累下來,以后再遇到這樣的問題直接朝這方面想就可以了~~

(想出貪心策略之后,自己構造幾組測試用例,如果沒有明顯的錯誤的話,直接寫代碼就 OK 了)(由于這里是賽后題解,我接下來會給出詳細證明)。

貪心策略的正確性證明:反證法(有興趣的可以看一看下面)

我們假設不是按照下標一位一位對應,只需要證明這樣反著來絕對沒有正著來更優就可以了。

假設 i < j,a[i] <= a[j],b[i] <= b[j]:

如果正著來的話,我們會讓 a[i] 和 b[i] 對應,a[j] 和 b[j] 對應。

如果反著來的話,我們會讓 a[i] 和 b[j] 對應,a[j] 和 b[i] 對應。

接下來只需要證明在所有的情況下反著來都沒有正著來更優就可以了。

我們根據 a[i] a[j] b[i] b[j] 的位置(大小關系)分情況討論:

其余情況都類似,就不一一列舉了!!!

【代碼實現】

#include <iostream>
#include <algorithm>
#include <cmath>using namespace std;typedef long long LL;
const int N = 5e4 + 10;int n;
LL a[N], b[N];int main()
{cin >> n;for(int i = 1; i <= n; i++) cin >> a[i];for(int i = 1; i <= n; i++) cin >> b[i];sort(a + 1, a + 1 + n);sort(b + 1, b + 1 + n);LL ret = 0;for(int i = 1; i <= n; i++)	ret += abs(a[i] - b[i]);cout << ret << endl;return 0;
}

題目五:冷熱數據隊列

題目鏈接:冷熱數據隊列

【題目描述】

【算法原理】

數據結構 + 模擬

1. 查找 :哈希表、紅黑樹;

2. 頭插:鏈表,雙端隊列;

3. 任意位置刪除:雙向鏈表;

4. 尾刪:鏈表,雙端隊列;

由于本題我們需要執行查找操作,因此我們需要哈希表(或紅黑樹)這一數據結構。

我們還需要執行任意位置刪除和頭插操作,因此我們需要雙向鏈表。(STL 中的 List 就行)

執行查找操作要用到的哈希表要能夠配合雙向鏈表的刪除操作,因此我們這樣創建哈希表:

至于 STL 中的 list,我們之前很少使用,這里給大家一些常見的接口:

接下來就是根據題目要求進行模擬的過程了,廢話不多說,直接來看代碼。?

【代碼實現】

#include <iostream>
#include <list>
#include <unordered_map>using namespace std;int n1, n2, m;
list<int> q1, q2;
unordered_map<int, list<int>::iterator> mp1, mp2;int main()
{cin >> n1 >> n2 >> m;while(m--){int x; cin >> x;if(mp1.count(x)){// ?q1.erase(mp1[x]);mp1.erase(x);// ? q1.push_front(x);mp1[x] = q1.begin();}else if(mp2.count(x)){// ?q2.erase(mp2[x]);mp2.erase(x);// ? q1.push_front(x);mp1[x] = q1.begin();}else{q2.push_front(x);mp2[x] = q2.begin();}if(q1.size() > n1){int x = *q1.rbegin();q1.pop_back();mp1.erase(x);q2.push_front(x);mp2[x] = q2.begin();}if(q2.size() > n2){int x = *q2.rbegin();q2.pop_back();mp2.erase(x);}}for(auto x : q1) cout << x << " ";cout << endl;for(auto x : q2) cout << x << " ";cout << endl; return 0;
} 

題目六:倒水

題目鏈接:倒水

【題目描述】

【算法原理】

二分答案

這道題目有明顯的二分題眼,要求的是最小值最大是多少。

分析二段性:

我們假設最終答案?ret 表示最小值的最大情況,我們發現如果再大于 ret 的話,是沒有辦法做到的,如果小于 ret 的話,我們是可以做到的。因此本題具有明顯的二段性,我們就可以嘗試使用二分答案來進行解決

接下來思考如何實現 check 函數?

我們傳入一個值 mid,check 函數的功能是判斷能否通過倒水使得所有瓶子中的最小值大于等于 x,如果能,說明 mid 落在了左區間。如果不能說明 mid 落到了右區間。

我們只需要從前往后遍歷一遍數組,只要該位置的水量大于等于 x,我們就把多余的水往后倒,如果遍歷到某一位置發現水量小于 x,就返回 false,如果全部大于等于 x,就返回 true;

我們直接來看代碼:

【代碼實現】

#include <iostream>
#include <cstring>using namespace std;typedef long long LL;
const int N = 1e5 + 10;LL n, k; 
LL a[N];
LL b[N];bool check(LL x)
{memcpy(b, a, sizeof a);for(int i = 1; i <= n; i++){if(b[i] < x) return false;b[i] -= x;if(i + k <= n) b[i + k] += b[i];} return true;
}int main()
{cin >> n >> k;for(int i = 1; i <= n; i++) cin >> a[i];int l = 0, r = 1e5;while(l < r){int mid = (l + r + 1) >> 1;if(check(mid)) l = mid;else r = mid - 1;}cout << l << endl;return 0;
}

題目七:拼好數

題目鏈接:拼好數

【題目描述】

【算法原理】

貪心 + 分類討論

這道題首先大家都可以想到是要統計每一個數中 6 的個數,然后再考慮拼接的問題。

我們預處理出一個 cnt 數組,其中 cnt[i] 表示:出現 6 的次數為 i 時,一共有多少個數。

比如,以第二個測試用例為例,cnt[6] = 1,cnt[3] = 3,cnt[1] = 3;

貪心策略:

1. 如果一個數 6 的出現次數大于等于 6,直接讓 ret + 1 即可,這個數可以單獨成為一個小組。

2. 如果能用 1 去湊,就盡量先使用 1 去湊;因為1 不能單獨湊成 6,只能和別的數配合使用。

? ? 能用 1 就先用 1,這樣就可以把其余更有用的數保留下來,去湊更多的可能性。

3. 在第二點的基礎上,如果能用更少的數湊成,就不用更多的數。

4. 在前面幾點的基礎上,優先用更容易湊出 6 的數去拼湊。?

直觀感受一下,這個貪心策略肯定是正確的~~~

那我們就確定了各種拼湊方式的優先級:

然后我們就可以去寫代碼了,廢話不多說,直接來看代碼:

【代碼實現】

#include <iostream>using namespace std;const int N = 10;int n;
int cnt[N];// 統計 6 出現的次數 
int calc(int x)
{int c = 0;while(x){if(x % 10 == 6) c++;x /= 10;}return c;
}int main()
{cin >> n;int ret = 0;for(int i = 1; i <= n; i++){int x; cin >> x;int t = calc(x);if(t >= 6) ret++;else cnt[t]++;}// 分類討論if(cnt[5]){// 5 + 1  5 + 2  5 + 3  5 + 4 for(int i = 1; i <= 4 && cnt[5]; i++){// cnt[i] + cnt[5]if(cnt[5] <= cnt[i]){ret += cnt[5];cnt[i] -= cnt[5];cnt[5] = 0;} else{ret += cnt[i];cnt[5] -= cnt[i];cnt[i] = 0;}} ret += cnt[5] / 2;} if(cnt[4]){// 4 + 1 + 1if(cnt[4] * 2 <= cnt[1]){ret += cnt[4];cnt[1] -= cnt[4] * 2;cnt[4] = 0; } else{ret += cnt[1] / 2;cnt[4] -= cnt[1] / 2;cnt[1] %= 2;}// 4 + 2  4 + 3for(int i = 2; i <= 3 && cnt[4]; i++){// cnt[i] + cnt[4]if(cnt[4] < cnt[i]){ret += cnt[4];cnt[i] -= cnt[4];cnt[4] = 0;} else{ret += cnt[i];cnt[4] -= cnt[i];cnt[i] = 0;}} // 4 + 4ret += cnt[4] / 2;} if(cnt[3]){// 3 + 1 + 2if(cnt[1] && cnt[2]){int t = min(min(cnt[1], cnt[2]), cnt[3]);ret += t;cnt[1] -= t;cnt[2] -= t;cnt[3] -= t;}// 3 + 3ret += cnt[3] / 2;cnt[3] %= 2;// 3 + 2 + 2 -> 2 + 2 + 2 cnt[2] += cnt[3]; }ret += cnt[2] / 3;cout << ret << endl;return 0;
} 

題目八:登山

題目鏈接:登山

【題目描述】

【算法原理】

本場比賽的壓軸題目、逆序對、圖論、并查集、單調棧

首先我們要模擬一下輸入輸出樣例,弄明白題目讓我們做什么。

這道題目從起點的行走方式如下:

我們先不要考慮二維,可以發現:無論橫著看還是豎著看,只要是構成逆序對的話,就有雙向邊。

那么這道題目就可以轉化成一個圖論問題

由于二維坐標不好處理,我們先把二維坐標轉化成一維坐標

根據逆序對建圖之后,我們只需要統計每一個連通塊(并查集)的最大值,再把所有的點遍歷一遍,判斷它是在哪一個連通塊,直接累加上這個最大值就可以了。

接下來考慮下一個問題:如何把這個圖給建出來呢???

肯定不能直接把所有的逆序對都連上雙向邊,因為時間和空間都不允許。(共 nmm + mnn 條邊)

但是我們發現,圖是沒有必要完全建出來的,我們僅需搞定并查集能夠找到連通塊中的最大值就可以了。

因此,我們這樣來處理這個問題:(當成經驗積累下來)

我們從前往后遍歷數組,如果該元素比前一個位置小,就一直往前合并并查集,順便刪除合并過的元素,直到該元素比前面的元素大。再把該元素存儲起來。

類似單調棧的過程,我們用棧來模擬這個過程。

我們直接來看代碼:

【代碼實現】

#include <iostream>using namespace std;const int N = 1e6 + 10;int n, m;
int a[N];
int fa[N]; // 并查集
int st[N], top; // 棧// 二維轉一維
int get_id(int i, int j)
{return i * m + j;
} int find(int x)
{return fa[x] == x ? x : fa[x] = find(fa[x]);
}void merge(int x, int y)
{x = find(x), y = find(y);if(x == y) return;// 小的合并到大的 if(a[x] >= a[y]) fa[y] = x;else fa[x] = y;
}int main() 
{cin >> n >> m;for(int i = 1; i < n * m; i++) fa[i] = i;for(int i = 0; i < n; i++)for(int j = 0; j < m; j++)cin >> a[get_id(i, j)];// 建圖for(int i = 0; i < n; i++){top = 0;for(int j = 0; j < m; j++){int t = top, id = get_id(i, j);while(top && a[st[top]] > a[id]){merge(st[top], id);top--;}if(t == top) st[++top] = id;else st[++top] = st[t];}} for(int j = 0; j < m; j++){top = 0;for(int i = 0; i < n; i++){int t = top, id = get_id(i, j);while(top && a[st[top]] > a[id]){merge(st[top], id);top--;}if(t == top) st[++top] = id;else st[++top] = st[t];}} double ret = 0;for(int i = 0; i < n * m; i++) ret += a[find(i)];printf("%.6lf\n", ret / (n * m));return 0;
}

好了,本期的內容就到這里了。期待我們下次見面。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/96345.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/96345.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/96345.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

項目幫助文檔的實現

項目幫助文檔的實現 代碼如下&#xff1a; #ifndef __M_HELPER_H__ #define __M_HELPER_H__ #include <iostream> #include <fstream> #include <string> #include <vector> #include <sqlite3.h> #include <random> #include <sstream…

python逆向-逆向pyinstaller打包的exe程序反編譯獲取源代碼

python逆向-逆向pyinstaller打包的exe程序反編譯獲取源代碼 Pyinstaller pyinstaller 是一個用于將 Python 程序打包成獨立可執行文件的工具&#xff0c;能夠在沒有 Python 解釋器的情況下運行。 Python 腳本轉換為 Windows、macOS 和 Linux 操作系統上的可執行文件。 把Python…

【SQL】-- sql having 和 where 的 區別

HAVING 和 WHERE 都是用來篩選數據的&#xff0c;但它們的應用場景有所不同。WHERE&#xff1a;用于篩選行數據&#xff0c;通常在 FROM 子句之后執行。它在分組操作 (GROUP BY) 之前應用&#xff0c;用來篩選出符合條件的記錄。示例&#xff1a;SELECT name, age FROM employe…

MySQL,SQL Server,PostgreSQL三種數據庫各自的優缺點,分別適用哪些場景

MySQL的優缺點及適用場景優點開源免費&#xff0c;社區版可商用&#xff0c;成本低。輕量級&#xff0c;安裝配置簡單&#xff0c;適合中小型項目。讀寫性能優異&#xff0c;尤其在OLTP&#xff08;在線事務處理&#xff09;場景下表現突出。支持主從復制、分片等擴展方案&…

Java 類加載機制雙親委派與自定義類加載器

我們來深入解析 Java 類加載機制。這是理解 Java 應用如何運行、如何實現插件化、以及解決一些依賴沖突問題的關鍵。一、核心概念&#xff1a;類加載過程一個類型&#xff08;包括類和接口&#xff09;從被加載到虛擬機內存開始&#xff0c;到卸載出內存為止&#xff0c;它的整…

Kaggle項目實踐——Titanic: Machine Learning from Disaster

泰坦尼克號沉船事件是機器學習領域最經典的入門項目之一。Kaggle 上的 Titanic: Machine Learning from Disaster 競賽&#xff0c;被無數人稱為“機器學習的 Hello World”。 一、數據導入與清洗&#xff1a;讓數據從 “雜亂” 變 “干凈” 機器學習模型就像 “挑食的孩子”…

Qt C++ 復雜界面處理:巧用覆蓋層突破復雜界面處理難題?之二

接上一篇&#xff0c;繼續探索“覆蓋層”的使用方法。 五、覆蓋層進階交互&#xff1a;從 “能繪制” 到 “好操作”? 基礎的繪制功能只能滿足 “看得見” 的需求&#xff0c;實際開發中還需要 “能操作”—— 比如選中線條修改顏色、按 Delete 鍵刪除線條、鼠標 hover 時高亮…

神經網絡構成框架-理論學習

一、神經網絡的基本組成與分類 1.1 神經網絡的核心組成部分 神經網絡是現代人工智能的基石&#xff0c;其設計靈感來源于生物神經系統的信息處理方式。作為工程師&#xff0c;了解神經網絡的基本組成部分對于構建和優化模型至關重要。一個典型的神經網絡主要由以下幾個關鍵部分…

從0開始開發app(AI助手版)-架構及環境搭建

架構選擇 前端React Native 后端Firebase 原因 環境準備 安裝node 安裝JDK 命令行工具&#xff1a;Node.js command prompt命令行查詢Javav版本&#xff1a;javac -version使用nrm工具切換淘寶源&#xff1a;npx nrm use taobao安裝yarn&#xff0c;替代npm下載工具&#x…

【性能測試】Jmeter工具快速上手-搭建壓力測試腳本

&#x1f525;個人主頁&#xff1a; 中草藥 &#x1f525;專欄&#xff1a;【Java】登神長階 史詩般的Java成神之路 概念 性能測試是軟件測試的重要分支&#xff0c;核心目標是通過模擬真實業務場景和負載壓力&#xff0c;評估系統在不同條件下的性能表現&#xff0c;發現系統性…

oracle里的int類型

oracle里的int類型 在 ANSI SQL 標準 中&#xff0c;INTEGER 和 SMALLINT 是定義好的精確數值類型&#xff0c;但它們的 “長度”或“大小”并不是通過 (N) 括號來指定的&#xff08;如 INT(4)&#xff09;&#xff0c;這一點與 MySQL 等數據庫的非標準擴展完全不同。 SMALLI…

前端學習之后端java小白(二)-sql約束/建表

一、約束SQL約束&#xff08;Constraints&#xff09;是用于限制表中數據的規則&#xff0c;確保數據的完整性和準確性。以下是主要的SQL約束類型&#xff1a; 主要約束類型&#xff1a; 1. NOT NULL 約束: 確保列不能包含空值 CREATE TABLE users (id INT NOT NULL,name VARC…

OpenCV:圖像金字塔

文章目錄一、什么是圖像金字塔&#xff1f;二、圖像金字塔的核心操作&#xff1a;采樣與逆采樣1. 向下采樣&#xff08;pyrDown&#xff09;&#xff1a;從高分辨率到低分辨率步驟1&#xff1a;高斯濾波步驟2&#xff1a;刪除偶數行與偶數列OpenCV實戰代碼效果特點2. 向上采樣&…

LVS與Keepalived詳解(一)負載均衡集群介紹

文章目錄前言一、什么是LVS&#xff1f;二、四層&#xff08;L4&#xff09;負載均衡的最佳解決方案是什么&#xff1f;2.1解決方案分類與對比&#xff08;負載均衡的三種方式介紹&#xff09;2.1.1 硬件負載均衡 (Hardware Load Balancer)2.1.2 軟件負載均衡 (Software Load B…

消息隊列-kafka完結

基本概念和操作 基本概念 簡單概念:::color4 Broker&#xff1a;如果將kafka比喻成數據倉庫網絡&#xff0c;那么Broker就是網絡中的倉庫節點&#xff0c;比如快遞站&#xff0c;在該節點內可以獨立運行&#xff0c;并且多個Broker可以連接起來&#xff0c;構建kafka集群Topic&…

Chromium 138 編譯指南 Windows篇:環境變量配置與構建優化(三)

引言配置&#xff0c;往往決定成敗。在軟件開發的世界里&#xff0c;環境變量就像是一位無聲的指揮家&#xff0c;默默地協調著各個組件的協同工作。對于Chromium 138這樣一個擁有數千萬行代碼的超大型項目而言&#xff0c;正確的環境變量配置更是編譯成功的關鍵所在。也許您曾…

LabVIEW加載 STL 模型至 3D 場景 源碼見附件

LabVIEW 中 STL 模型的導入與 3D 場景顯示&#xff0c;基于示例代碼邏輯&#xff0c;結合格式兼容性、功能實現步驟及多樣化顯示方式&#xff0c;適用于三維可視化溫控、機械零件模擬等場景。 1示例代碼 NI 社區案例 “Add an STL file to 3D scene using LabVIEW” 提供了經…

硅基計劃3.0 Map類Set類

文章目錄一、二叉搜索樹&#xff08;排序樹&#xff09;1. 概念初識2. 模擬實現1. 創建搜索樹節點2. 查找指定元素是否存在3. 插入4. 刪除二、Map類1. put——設置單詞以及其頻次2. get——獲取單詞頻次3. getOrDefault——獲取單詞頻次或返回默認值4. remove——刪除單詞頻次信…

LeetCode 刷題【73. 矩陣置零】

73. 矩陣置零 自己做 解&#xff1a;標記消除 class Solution { public:void setZeroes(vector<vector<int>>& matrix) {vector<bool> x(matrix.size(), false); //要置0的行vector<bool> y(matrix[0].size(), false); //…

Unity學習----【進階】TextMeshPro學習(一)--基礎知識點

來源于唐老獅的視頻教學&#xff0c;僅作記錄和感悟記錄&#xff0c;方便日后復習或者查找 一.導入TextMeshPro 對于新創建的工程&#xff0c;可以直接在這里導入TMP必要的資源&#xff08;上面&#xff09;&#xff0c;以及TMP的實例和擴展&#xff08;下面&#xff09; 導入之…