第十屆藍橋杯c/c++語言程序設計省賽大學B組於3月24日(9h-13h)結束了。。。
2019藍橋杯這次比賽我是完全打鐵了。。。
完全不敢相信,大家都說這次題目有點水,10題我也就僅僅做了6題,更重要的是,沒拿到獎,很遺憾。
A題:組隊
作為籃球隊教練,你需要從以下名單中選出 1 號位至 5 號位各一名球員,
組成球隊的首發陣容。
每位球員擔任 1 號位至 5 號位時的評分如下表所示。請你計算首發陣容 1
號位至 5 號位的評分之和最大可能是多少?
注意:這里一個人只能站一個位。
這題有很多種站法,也很簡單,心算就ok,我就挑了一種,但答案唯一。

490
B題:年號字串
小明用字母 A 對應數字 1,B 對應 2,以此類推,用 Z 對應 26。對於 27
以上的數字,小明用兩位或更長位的字符串來對應,例如 AA 對應 27,AB 對
應 28,AZ 對應 52,LQ 對應 329。
請問 2019 對應的字符串是什么?
對於這道題我當時是做錯的了,兩次了,這么簡單都不會。
方法1:照搬excel的頭行的字串
方法2:
#include <stdio.h> void dfs(int n){ if(n>26) dfs((n-1)/26);///n-1都是為下面+'A'做准備 putchar('A'+(n-1)%26); } int main(){ int n; while(~scanf("%d",&n)){ dfs(n); puts(""); } return 0; }
說到這里,每次都進入遞歸的死胡同,以上先進行完if,以為n已經改變,這是明顯進入了死胡同。n還是原來,親。

BYQ
C題: 數列求值
給定數列 1, 1, 1, 3, 5, 9, 17, …,從第 4 項開始,每項都是前 3 項的和。求
第 20190324 項的最后 4 位數字。
這題也是,這么簡單,居然拖到最后,甚至還用了java去編。大一真不知道自己是怎么過來,打鐵唄,還說是集訓隊出來的。
方法水的一匹(遞推:從第四項開始,每一項都是前面三項之和),居然沒想到模,這么大的數。。。(好歹最后做對了)
#include <stdio.h> int main(){ int a,b,c,d; a=1; b=1; c=1; for(int i=4;i<=20190324;i++){ d=(a+b+c)%10000; a=b; b=c; c=d; } printf("%d\n",d); return 0; }
答案:

4659
D題:數的分解
把 2019 分解成 3 個各不相同的正整數之和,並且要求每個正整數都不包
含數字 2 和 4,一共有多少種不同的分解方法?
注意交換 3 個整數的順序被視為同一種方法,例如 1000+1001+18 和
1001+1000+18 被視為同一種。
我不記得這題是否做對。
#include<stdio.h> bool panduan(int x){ for(;x>0;x/=10) if(x%10==2||x%10==4) return false; return true; } int main(){ int n = 2019; int tnt = 0; for(int i=1;i<n/3;i++) if(panduan(i)){ for(int j=i+1;n-i-j>j;j++) if(panduan(j)&&panduan(n-i-j))++tnt;///大於j防止重復 } printf("%d\n",tnt); return 0; }

40785
E題:迷宮
下圖給出了一個迷宮的平面圖,其中標記為 1 的為障礙,標記為 0 的為可
以通行的地方。
010000
000100
001001
110000
迷宮的入口為左上角,出口為右下角,在迷宮中,只能從一個位置走到這
個它的上、下、左、右四個方向之一。
對於上面的迷宮,從入口開始,可以按DRRURRDDDR 的順序通過迷宮,
一共 10 步。其中 D、U、L、R 分別表示向下、向上、向左、向右走。
對於下面這個更復雜的迷宮(30 行 50 列),請找出一種通過迷宮的方式,
其使用的步數最少,在步數最少的前提下,請找出字典序最小的一個作為答案。
請注意在字典序中D<L<R<U。
01010101001011001001010110010110100100001000101010 00001000100000101010010000100000001001100110100101 01111011010010001000001101001011100011000000010000 01000000001010100011010000101000001010101011001011 00011111000000101000010010100010100000101100000000 11001000110101000010101100011010011010101011110111 00011011010101001001001010000001000101001110000000 10100000101000100110101010111110011000010000111010 00111000001010100001100010000001000101001100001001 11000110100001110010001001010101010101010001101000 00010000100100000101001010101110100010101010000101 11100100101001001000010000010101010100100100010100 00000010000000101011001111010001100000101010100011 10101010011100001000011000010110011110110100001000 10101010100001101010100101000010100000111011101001 10000000101100010000101100101101001011100000000100 10101001000000010100100001000100000100011110101001 00101001010101101001010100011010101101110000110101 11001010000100001100000010100101000001000111000010 00001000110000110101101000000100101001001000011101 10100101000101000000001110110010110101101010100001 00101000010000110101010000100010001001000100010101 10100001000110010001000010101001010101011111010010 00000100101000000110010100101001000001000000000010 11010000001001110111001001000011101001011011101000 00000110100010001000100000001000011101000000110011 10101000101000100010001111100010101001010000001000 10000010100101001010110000000100101010001011101000 00111100001000010000000110111000000001000000001011 10000001100111010111010001000110111010101101111000
對於這題,我剛開始有點懵,這么多數字,1500啊。真是的,沒見過大世面嗎。只要熟練dfs與bfs肯定沒問題,稍微注意就是條件:步數最小,字典序最小。
唉,我沒做出來。
方法1:把迷宮放到excel上,會玩迷宮的你懂的,反正路線唯一。
方法2:
#include <stdio.h> #include <string.h> #include <queue> using namespace std; const int xx[4]={1,0,0,-1}; const int yy[4]={0,-1,1,0}; const char *s = "DLRU"; char a[100][100]; int r[100][100]; typedef pair<int ,int>p; int n,m; void dfs(int x,int y){ if(x!=1||y!=1){ int t=r[x][y]; dfs(x-xx[t],y-yy[t]); putchar(s[t]); } } void bfs(){ queue<p>que; que.push(p(1,1)); a[1][1] = '1'; while(!que.empty()){ int x=que.front().first; int y=que.front().second; que.pop(); int nx,ny; for(int i=0;i<4;i++){ nx=x+xx[i]; ny=y+yy[i]; if(a[nx][ny]=='0'){ a[nx][ny]='1'; que.push(p(nx,ny)); r[nx][ny]=i; } } } dfs(n,m); } int main(){ n=30,m=50; for(int i=1;i<=n;i++) scanf("%s",&a[i][1]); bfs(); return 0; }
參考了大佬的代碼,我發覺我的基礎賊不扎實,bfs求出就是最小步,這是固定的,我們需要注意的就是字典序。我們可以先排好上下左右字母與方向一致。
還有遞歸,兄dei要回去復習了,上面那個遞歸剛開始看不明白,聽了舍友的分析以及回去看看c,哎呀,遞歸:一層一層迭代下去,直到找到最終結束值或初始值,然后一層一層返回。傻了唄!!!

1 DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR
F題:特別數的和
小明對數位中含有 2、0、1、9 的數字很感興趣(不包括前導 0),在 1 到
40 中這樣的數包括 1、2、9、10 至 32、39 和 40,共 28 個,他們的和是 574。
請問,在 1 到 n 中,所有這樣的數的和是多少?
【輸入格式】
輸入一行包含兩個整數 n。
【輸出格式】
輸出一行,包含一個整數,表示滿足條件的數的和。
【樣例輸入】
40
【樣例輸出】
574
【評測用例規模與約定】
對於 20% 的評測用例,1 ≤ n ≤ 10。
對於 50% 的評測用例,1 ≤ n ≤ 100。
對於 80% 的評測用例,1 ≤ n ≤ 1000。
對於所有評測用例,1 ≤ n ≤ 10000。
這題我覺得應該是沒過的,剛開始是不斷暴力,居然運行不出,真是丟臉。最后想了一個很lou的方法,又復雜的,后台數據應該能過一些。
#include <stdio.h> bool panduan(int x){ for(;x>0;x/=10){ int t=x%10; if(t==2||t==0||t==1||t==9) return true; } return false; } int main(){ int n; scanf("%d",&n); int tnt=0; for(int i=1;i<=n;i++) if(panduan(i)) tnt+=i; printf("%d\n",tnt); return 0; }
這么簡單。。。靈活運用。
G題:完全二叉樹的權值
給定一棵包含 N 個節點的完全二叉樹,樹上每個節點都有一個權值,按從
上到下、從左到右的順序依次是 A 1 , A 2 , ··· A N ,如下圖所示:
現在小明要把相同深度的節點的權值加在一起,他想知道哪個深度的節點
權值之和最大?如果有多個深度的權值和同為最大,請你輸出其中最小的深度。
注:根的深度是 1。
【輸入格式】
第一行包含一個整數 N。
第二行包含 N 個整數 A 1 , A 2 , ··· A N 。
【輸出格式】
輸出一個整數代表答案。
【樣例輸入】
7
1 6 5 4 3 2 1
試題G: 完全二叉樹的權值 10
【樣例輸出】
2
【評測用例規模與約定】
對於所有評測用例,1 ≤ N ≤ 100000,−100000 ≤ A i ≤ 100000
#include <stdio.h> int a[100010]; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",a+i); long long maxx = -100000; int ans=1; for(int i=1;(1<<(i-1))<=n;i++){///i代表樹的深度 long long t = 0; for(int j=1<<(i-1);j<(1<<i)&&j<=n;j++) t+=a[j];///位運算只要控制層的可用范圍 if(maxx<t){ maxx=t; ans=i; } } printf("%d\n",ans); return 0; }
看到這題時間只剩最后一個小時了,由於時間問題我沒做。但肯定的是我也不能做出來,由於這題這方法我也想不出來,位運算也不是經常用。
H題:等差數列
數學老師給小明出了一道等差數列求和的題目。但是粗心的小明忘記了一
部分的數列,只記得其中 N 個整數。
現在給出這 N 個整數,小明想知道包含這 N 個整數的最短的等差數列有
幾項?
【輸入格式】
輸入的第一行包含一個整數 N。
第二行包含 N 個整數 A 1 ,A 2 ,··· ,A N 。(注意 A 1 ∼ A N 並不一定是按等差數
列中的順序給出)
【輸出格式】
輸出一個整數表示答案。
【樣例輸入】
5
2 6 4 10 20
【樣例輸出】
10
【樣例說明】
包含 2、6、4、10、20 的最短的等差數列是 2、4、6、8、10、12、14、16、
18、20。
#include <stdio.h> #include <algorithm> using namespace std; int a[100010]; int gcd(int a,int b){ if(!b) return a; return gcd(b,a%b); } int main(){ int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",a+i); sort(a,a+n); int d; d=a[1]-a[0]; if(d==0) return printf("%d\n",d),0; for(int i=2;i<n;i++) d=gcd(d,a[i]-a[i-1]); printf("%d\n",(a[n-1]-a[0])/d+1); return 0; }
這題我是用c++的,咋知道現場只提供Devc++居然編譯不了,然后數據都沒測,直接交上去;我感覺是懸啊,沒有想到最大公約。。。
最后兩題沒看就先不總結了,有待去總結。。。
I題:后綴表達式
J題:靈能傳輸
對於藍橋杯省賽如果能保證8題全對,我覺得省一是沒問題的,然后就是平時實力要過硬,保證基礎扎實,多刷題。。。菜鳥的我,還是好好努力,多刷題,為2020藍橋杯做好准備吧!!!挑戰java!
參考資料:https://blog.csdn.net/Dragon_fxl/article/details/88776273
https://cloud.tencent.com/developer/article/1408608