第八届蓝桥杯大赛个人赛决赛(CB软件类)真题
一、試題A:36進制
標題:36進制
對于16進制,我們使用字母A-F來表示10及以上的數字。
如法炮制,一直用到字母Z,就可以表示36進制。
36進制中,A表示10,Z表示35,AA表示370
你能算出 MANY 表示的數字用10進制表示是多少嗎?
請提交一個整數,不要填寫任何多余的內容(比如,說明文字)
代碼如下:
//ans = 1040254 #include<iostream>using namespace std;string s;int main(){cin >> s;int ans = 0,p = 1,d = 36;for(int i = s.size() - 1; i >= 0; i -- ){ans += (s[i] - 'A' + 10) * p;p *= d;}cout << ans;return 0; }二、試題B: 磁磚樣式
標題:磁磚樣式
小明家的一面裝飾墻原來是 3*10 的小方格。
現在手頭有一批剛好能蓋住2個小方格的長方形瓷磚。
瓷磚只有兩種顏色:黃色和橙色。
小明想知道,對于這么簡陋的原料,可以貼出多少種不同的花樣來。
小明有個小小的強迫癥:忍受不了任何2*2的小格子是同一種顏色。
(瓷磚不能切割,不能重疊,也不能只鋪一部分。另外,只考慮組合圖案,請忽略瓷磚的拼縫)
顯然,對于 2*3 個小格子來說,口算都可以知道:一共10種貼法,如【p1.png所示】
但對于 3*10 的格子呢?肯定是個不小的數目,請你利用計算機的威力算出該數字。
注意:你需要提交的是一個整數,不要填寫任何多余的內容(比如:說明性文字)
代碼如下:
//ans = 101466 #include<iostream> #include<set>using namespace std;const int N = 20;/*剛好能蓋住2個小方格的長方形瓷磚忍受不了任何2*2的小格子是同一種顏色3*10 的格子*/ int n,m; char s[N][N]; string ans; set<string> res;int judge(int x,int y){if(x < 0 || x > n - 1 || y < 0 || y > m - 1) return 0;return s[x][y]; } bool check(int x,int y){//左上角if(judge(x - 1,y) == s[x][y] && judge(x,y - 1) == s[x][y] && judge(x - 1,y - 1) == s[x][y]) return false;//右上角if(judge(x - 1,y) == s[x][y] && judge(x,y + 1) == s[x][y] && judge(x - 1,y + 1) == s[x][y]) return false; //左下角if(judge(x,y - 1) == s[x][y] && judge(x + 1,y) == s[x][y] && judge(x + 1,y - 1) == s[x][y]) return false;//右下角if(judge(x,y + 1) == s[x][y] && judge(x + 1,y) == s[x][y] && judge(x + 1,y + 1) == s[x][y]) return false;return true; } void dfs(int sum){if(sum >= n * m){ans = "";for(int i = 0; i < n; i ++ ){ans += s[i];}res.insert(ans);return ;}int x = sum / m;int y = sum % m;//如果該點已經有顏色,那么繼續搜索其他點 if(s[x][y]) dfs(sum + 1);else{//縱向搜索下邊那個點 if(x < n - 1 && !s[x + 1][y]){s[x][y] = 1;s[x + 1][y] = 1;if(check(x,y) && check(x + 1,y)) dfs(sum + 1);s[x][y] = 2;s[x + 1][y] = 2;if(check(x,y) && check(x + 1,y)) dfs(sum + 1);s[x][y] = 0;s[x + 1][y] = 0;}//橫向搜索右邊那個點 if(y < m - 1 && !s[x][y + 1]){s[x][y] = 1;s[x][y + 1] = 1;if(check(x,y) && check(x,y + 1)) dfs(sum + 1);s[x][y] = 2;s[x][y + 1] = 2;if(check(x,y) && check(x,y + 1)) dfs(sum + 1);s[x][y] = 0;s[x][y + 1] = 0; }} } int main(){n = 3, m = 10;dfs(0); cout<<res.size();return 0; }三、試題C:希爾伯特曲線
標題:希爾伯特曲線
標題:希爾伯特曲線希爾伯特曲線是以下一系列分形曲線 Hn 的極限。我們可以把 Hn 看作一條覆蓋 2^n × 2^n 方格矩陣的曲線,曲線上一共有 2^n × 2^n 個頂點(包括左下角起點和右下角終點),恰好覆蓋每個方格一次。[p1.png]Hn(n > 1)可以通過如下方法構造: 1. 將 Hn-1 順時針旋轉90度放在左下角 2. 將 Hn-1 逆時針旋轉90度放在右下角 3. 將2個 Hn-1 分別放在左上角和右上角 4. 用3條單位線段把4部分連接起來對于 Hn 上每一個頂點 p ,我們定義 p 的坐標是它覆蓋的小方格在矩陣中的坐標(左下角是(1, 1),右上角是(2^n, 2^n),從左到右是X軸正方向,從下到上是Y軸正方向), 定義 p 的序號是它在曲線上從起點開始數第幾個頂點(從1開始計數)。以下程序對于給定的n(n <= 30)和p點坐標(x, y),輸出p點的序號。請仔細閱讀分析源碼,填寫劃線部分缺失的內容。#include <stdio.h>long long f(int n, int x, int y) {if (n == 0) return 1;int m = 1 << (n - 1);if (x <= m && y <= m) {return f(n - 1, y, x);}if (x > m && y <= m) {return 3LL * m * m + f(n - 1, ________________ , m * 2 - x + 1); // 填空}if (x <= m && y > m) {return 1LL * m * m + f(n - 1, x, y - m);}if (x > m && y > m) {return 2LL * m * m + f(n - 1, x - m, y - m);} }int main() {int n, x, y;scanf("%d %d %d", &n, &x, &y); printf("%lld", f(n, x, y));return 0; }注意:只填寫劃線處缺少的內容,不要填寫已有的代碼或符號,也不要填寫任何解釋說明文字等。四、試題D:發現環
標題:發現環
小明的實驗室有N臺電腦,編號1~N。原本這N臺電腦之間有N-1條數據鏈接相連,恰好構成一個樹形網絡。在樹形網絡上,任意兩臺電腦之間有唯一的路徑相連。
不過在最近一次維護網絡時,管理員誤操作使得某兩臺電腦之間增加了一條數據鏈接,于是網絡中出現了環路。環路上的電腦由于兩兩之間不再是只有一條路徑,使得這些電腦上的數據傳輸出現了BUG。
為了恢復正常傳輸。小明需要找到所有在環路上的電腦,你能幫助他嗎?
輸入
第一行包含一個整數N。
以下N行每行兩個整數a和b,表示a和b之間有一條數據鏈接相連。
對于30%的數據,1 <= N <= 1000
對于100%的數據, 1 <= N <= 100000, 1 <= a, b <= N
輸出
按從小到大的順序輸出在環路上的電腦的編號,中間由一個空格分隔。
輸入保證合法。
樣例輸入:
5 1 2 3 1 2 4 2 5 5 3樣例輸出:
1 2 3 5題目分析:
因為對于100%的數據,N非常大,那么就用鄰接表存儲圖
代碼如下:
#include<iostream> #include<vector> #include<algorithm>using namespace std;const int N = 1e5 + 10;int n; vector<int > g[N]; bool st[N]; int fa[N]; int start,ed; int ans[N];void init(){for(int i = 1; i <= n; i ++ ){fa[i] = i;} }int find(int x){if(fa[x] != x) fa[x] = find(fa[x]);return fa[x]; }void merge(int a,int b){fa[find(a)] = find(b); }void dfs(int u,int index){ans[index] = u;if(u == ed){sort(ans,ans + index + 1);for(int i = 0; i <= index; i ++ ){if(i) cout<<" ";cout<<ans[i];}puts("");} for(int i = 0; i < g[u].size(); i ++ ){int j = g[u][i];if(!st[j]){st[j] = true;dfs(j,index + 1);st[j] = false;}} } int main(){cin >> n;init();for(int i = 1; i <= n; i ++ ){int a,b; cin >> a >> b;if(find(a) != find(b)){merge(a,b);g[a].push_back(b);g[b].push_back(a);}else{start = a,ed = b;}}st[start] = true;dfs(start,0);return 0; }五、試題E:對局匹配
標題:對局匹配
小明喜歡在一個圍棋網站上找別人在線對弈。這個網站上所有注冊用戶都有一個積分,代表他的圍棋水平。
小明發現網站的自動對局系統在匹配對手時,只會將積分差恰好是K的兩名用戶匹配在一起。如果兩人分差小于或大于K,系統都不會將他們匹配。
現在小明知道這個網站總共有N名用戶,以及他們的積分分別是A1, A2, … AN。
小明想了解最多可能有多少名用戶同時在線尋找對手,但是系統卻一場對局都匹配不起來(任意兩名用戶積分差不等于K)?
輸入
第一行包含兩個個整數N和K。
第二行包含N個整數A1, A2, … AN。
對于30%的數據,1 <= N <= 10
對于100%的數據,1 <= N <= 100000, 0 <= Ai <= 100000, 0 <= K <= 100000
輸出
一個整數,代表答案。
樣例輸入:
10 0 1 4 2 8 5 7 1 4 2 8樣例輸出:
6樣例輸入:
10 1 2 1 1 1 1 4 4 3 4 4樣例輸出:
8一個整數,代表答案。
某大佬的題解,暫時沒看懂,占坑
六、試題F:觀光鐵路
【樣例輸入】
4 5 1 2 2 3 3 4 4 1 1 3【樣例輸出】
3.333333333333 5.000000000000 3.333333333333 5.000000000000【樣例輸入】
10 15 1 2 1 9 1 5 2 3 2 7 3 4 3 10 4 5 4 8 5 6 6 7 6 10 7 8 8 9 9 10【樣例輸出】
10.000000000000 10.000000000000 10.000000000000 10.000000000000 10.000000000000 10.000000000000 10.000000000000 10.000000000000 10.000000000000 10.000000000000【數據規模與約定】
對于10%的測試點,n ≤ 10;
對于20%的測試點,n ≤ 12;
對于50%的測試點,n ≤ 16;
對于70%的測試點,n ≤ 19;
對于100%的測試點,4 ≤ k ≤ n ≤ 21,1 ≤ u, v ≤ n。數據有梯度。
總結
以上是生活随笔為你收集整理的第八届蓝桥杯大赛个人赛决赛(CB软件类)真题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 哥德巴赫猜想c语言 思路,01-哥德巴赫
- 下一篇: JDO和JPA的区别是什么