2021年 第12届 蓝桥杯 第3次模拟赛真题详解及小结【Java版】
- 藍橋杯 Java B組 省賽決賽 真題詳解及小結匯總【2013年(第4屆)~2021年(第12屆)】
- 第11屆 藍橋杯-第1、2次模擬(軟件類)真題-(2020年3月、4月)-官方講解視頻
- 說明:大部分題解思路及程序代碼 源自?藍橋杯 官網視頻(Java B組歷年真題解析)?——?鄭未老師。
目錄
模擬賽網頁截圖
一、試題A——答案:800
解法一:循環+gcd()
二、試題B——答案:81
解法一
三、試題C——答案:12
解法一
解法二
四、試題D——答案:1001
解法一:概念計算
解法二
五、試題E——答案:BYS
解法一:手工計算
解法二
解法三:Excel列計算(通用版)
六、試題F
解法一
七、試題G
解法一【錯誤解法】
解法二
八、試題H
解法一
九、試題I
解法一
九、試題I(2)
解法一
十、試題J
解法一
小結
僅供參考,歡迎指正!以下均為個人想法和解題思路,如有錯誤或不足,歡迎指正。
模擬賽網頁截圖
?
一、試題A——答案:800
問題描述
請問在 1 到 2020 中,有多少個數與 2020 互質,即有多少個數與 2020 的最大公約數為 1。
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分。
解法一:循環+gcd()
【答案】:800
package simulationMatch_12_2021_3;public class _01A {public static void main(String[] args) {int answer = 0;for (int i = 1; i <= 2020; i++) {if (gcd(2020, i) == 1) { // 若兩數最大公約數是1,則answer++answer++;System.out.print(i + "、");}}System.out.println("\n" + answer);}/*** 返回最大公約數* * @param a* @param b* @return*/public static int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);} }二、試題B——答案:81
問題描述
ASCII 碼將每個字符對應到一個數值(編碼),用于信息的表示和傳輸。在 ASCII 碼中,英文字母是按從小到大的順序依次編碼的,例如:字母 A 編碼是 65, 字母 B 編碼是 66,字母 C 編碼是 67,請問字母 Q 編碼是多少?
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分。
解法一
【答案】:81
package simulationMatch_12_2021_3;public class _02B {public static void main(String[] args) {System.out.println('A' - 0); // 65System.out.println('B' - 0); // 66System.out.println('C' - 0); // 67System.out.println('Q' - 0); // 81System.out.println('Q' + 0); // 81System.out.println('Z' - 0); // 90} }三、試題C——答案:12
問題描述
對于整數 v 和 p,定義 Pierce 序列為:
a[1] = v
a[i] = p % a[i-1]
例如,當 v = 8, p = 21 時,對應的 Pierce 序列為
a[1] = 8
a[2] = 5
a[3] = 1
再往后計算,值變為 0,不在我們考慮的范圍內。因此當 v = 8, p = 21 時, Pierce 序列的長度為 3。
當 p 一定時,對于不同的 v 值,Pierce 序列的長度可能不同。當 p = 8 時,若 1<=v<p,最長的 Pierce 序列出現在 v=13時,為(13, 8, 5, 1),長度為 4。
當 p=2021 時,最長的 Pierce 序列出現在 v=1160 時,請問這個序列有多長?
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分。
解法一
【答案】:12
package simulationMatch_12_2021_3;public class _03C {public static void main(String[] args) {function(8, 21);System.out.println("--------------");function(13, 8);System.out.println("--------------");function(1160, 2021);}public static void function(int v, int p) {// int v = 8, p = 21;// int v = 13, p = 8;// int v = 1160, p = 2021;int Pierce[] = new int[100];Pierce[1] = v;for (int i = 2; i <= 50; i++) {if (Pierce[i - 1] != 0) {Pierce[i] = p % Pierce[i - 1];}}for (int i = 1; i <= 50; i++) {if (Pierce[i] != 0) {System.out.println(i + ": " + Pierce[i]);}}} }解法二
原文鏈接:1.0219——2021年第十二屆藍橋杯第三場校模擬賽
package simulationMatch_12_2021_3;public class _03C2 {public static void main(String[] args) {int v = 1160, p = 2021, ans = 1;while (p % v != 0) {v = p % v;++ans;}System.out.println(ans);} }四、試題D——答案:1001
問題描述
有一棵二叉樹,一個由2021個結點,其中有1000個結點有兩個子結點,其他的結點有一個或者0個子結點。
請問,這棵二叉樹有多少個葉結點?
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個整數,在提交答案時只填寫這個整數,填寫多余的內容將無法得分。
解法一:概念計算
【答案】:1001
- 非空二叉樹上的葉子結點數(度為0的節點,稱為“葉子結點”)等于度為2的結點數加1,即??。
- 設度為0、1、2的結點個數分別為、、,二叉樹的節點總數??。
n = n2?+ n1 + n0 = 2021,n2 = 1000,n0 = n2 + 1 = 1000 + 1 = 1001 。
解法二
【答案】:1001
package simulationMatch_12_2021_3;public class _04D {public static void main(String[] args) {System.out.println((int) (Math.pow(2, 10 - 1) - 23) * 2 + 23);} }五、試題E——答案:BYS
問題描述
在 Excel 中,第 1 列到第 26 列的列名依次為 A 到 Z,從第 27 列開始,列名有兩個字母組成,第 27 列到第 702 列的列名依次為 AA 到 ZZ。
之后的列再用 3 個字母、4 個字母表示。
請問,第 2021 列的列名是什么?
答案提交
這是一道結果填空的題,你只需要算出結果后提交即可。本題的結果為一個有大寫字母組成的字符串,在提交答案時只填寫這個字符串,填寫多余的內容將無法得分。
解法一:手工計算
【答案】:BYS
package simulationMatch_12_2021_3;public class _05E {public static void main(String[] args) {System.out.println(26); // 26【A-Z】System.out.println(26 * 26); // 676【AA-ZZ】676+26=702System.out.println(26 * 26 * 26); // 17576【AAA-ZZZ】System.out.println("---");for (int i = 703; i <= 2021; i += 26) {System.out.println(i);}} }解法二
原文鏈接:1.0219——2021年第十二屆藍橋杯第三場校模擬賽
package simulationMatch_12_2021_3;public class _05E2 {public static void main(String[] args) {int n = 2021;StringBuilder stb = new StringBuilder("");while (n != 0) {stb.append((char) (((n - 1) % 26) + 'A'));n = (n - 1) / 26;}System.out.println(stb.reverse().toString()); // BYS}}解法三:Excel列計算(通用版)
原文鏈接:LuckyCCat——【藍橋杯2017Java】Excel地址
package simulationMatch_12_2021_3;import java.util.Scanner;public class _05E3 {public static void main(String[] args) {Scanner input = new Scanner(System.in);int target = input.nextInt();char[] ans = new char[1000000];int index = 0;while (target > 0) {int temp = target % 26;if (temp == 0) { // 特殊情況,能除盡的情況下,26作為余數ans[index++] = 'Z';target = target / 26 - 1;} else { // 不需要進位ans[index++] = (char) ('A' + temp - 1); // 記錄余數target = target / 26; // 把商作為新的被除數}}for (int i = index - 1; i >= 0; i--) {System.out.print(ans[i]);}} }六、試題F
問題描述
在書寫一個較大的整數時,為了方便看清數位,通常會在數位之間加上逗號來分割數位,具體的,從右向左,每三位分成一段,相鄰的段之間加一個逗號。
例如,1234567 寫成 1,234,567。
例如,17179869184 寫成 17,179,869,184。
給定一個整數,請將這個整數增加分割符后輸出。
輸入格式
輸入一行包含一個整數 v。
輸出格式
輸出增加分割符后的整數。
樣例輸入
1234567
樣例輸出
1,234,567
樣例輸入
17179869184
樣例輸出
17,179,869,184
數據規模和約定
對于 50% 的評測用例,0 <= v < 10^9 (10的9次方)。
對于所有評測用例,0 <= v < 10^18 (10的18次方)。
解法一
原文鏈接:1.0219——2021年第十二屆藍橋杯第三場校模擬賽
package simulationMatch_12_2021_3;import java.util.Scanner;public class _06F {public static void main(String[] args) {Scanner sc = new Scanner(System.in);long v = sc.nextLong();char[] ch = new String(v + "").toCharArray();if (ch.length <= 3) {System.out.println(v);} else if (ch.length % 3 == 0) {System.out.print("" + ch[0] + ch[1] + ch[2]);for (int i = 3; i < ch.length; i += 3)System.out.print("," + ch[i] + ch[i + 1] + ch[i + 2]);} else {for (int i = 0; i < ch.length % 3; ++i)System.out.print(ch[i]);for (int i = ch.length % 3; i < ch.length; i += 3)System.out.print("," + ch[i] + ch[i + 1] + ch[i + 2]);}} }七、試題G
問題描述
斐波那契數列是這樣一個數列:它的第一項和第二項都是1,從第三項開始每一項都是前兩項的和。
根據以上定義,我們容易計算出斐波那契數列的前幾項依次是:1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ……
現在請你計算斐波那契數列第N項是奇數還是偶數?
輸入格式
輸入的包含一個整數N。
輸出格式
如果是奇數輸出1,是偶數輸出0。
樣例輸入
10
樣例輸出
1
提示
找規律。
數據規模和約定
對于所有評測用例,1 <= N <= 1000000000。
解法一【錯誤解法】
package simulationMatch_12_2021_3;import java.math.BigInteger; import java.util.Scanner;public class _07G {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();BigInteger fib[] = new BigInteger[10001];fib[1] = new BigInteger("1");fib[2] = new BigInteger("1");for (int i = 3; i <= 1000; i++) {fib[i] = fib[i - 1].add(fib[i - 2]);System.out.println(i + ": " + fib[i]);}if (fib[n].mod(new BigInteger("2")) != null) {System.out.println(1);} else {System.out.println(0);}} // public static void testLong() { // // System.out.println(Integer.MAX_VALUE);//2 147 483 647 // Scanner sc = new Scanner(System.in); // int n = sc.nextInt();// 1 <= N <= 1 000 000 000 // long fib[] = new long[1000]; // fib[1] = 1l; // fib[2] = 1l; // for (int i = 3; i <= 100; i++) { // fib[i] = fib[i - 1] + fib[i - 2]; // System.out.println(i + ": " + fib[i]); // } // // if (fib[n] % 2 == 0) { // System.out.println(1); // } else { // System.out.println(0); // } // } }解法二
原文鏈接:1.0219——2021年第十二屆藍橋杯第三場校模擬賽
package simulationMatch_12_2021_3;import java.util.Scanner;public class _07G2 {public static void main(String[] args) {// 對于 50% 的評測用例,0 <= v < 10^9 (10的9次方)。// 對于所有評測用例, 0 <= v < 10^18 (10的18次方)。Scanner sc = new Scanner(System.in); // String str = sc.nextLine(); // System.out.println(str);int n = sc.nextInt();if (n % 3 == 0) {System.out.println(0);} else {System.out.println(1);}} }八、試題H
問題描述
給定一個矩陣 M,由 n 行 m 列組成,第 i 行第 j 列值為 M[i][j]。
定義矩陣 M 的重量為矩陣中所有元素的和,幾位weight(M)
請找到矩陣左上角的一個子矩陣S(矩陣的前 r 行中的前 c 列組成),使得這個子矩陣的重量的兩倍最接近矩陣 M 重量。即 |2 weight(S)-weight(M)| 最小。
如果有多個子矩陣滿足條件,請找出面積 r * c 最小的一個。
如果仍然有多個子矩陣滿足條件,請找出其中 r 最小的一個。
輸入格式
輸入第一行包含兩個整數 n, m,表示矩陣的大小。
接下來 n 行,每行 m 個整數,表示給定的矩陣M。
輸出格式
輸出一行,包含兩個整數 r, c,表示子矩陣為矩陣 M 的前 r 行中的前 c 列。
樣例輸入
3 4
3 0 1 1
1 0 1 1
1 1 -2 4
樣例輸出
2 3
數據規模和約定
對于 30% 的評測用例,1 <= n, m <= 20, -10 <= M[i][j] <= 10。
對于 50% 的評測用例,1 <= n, m <= 100, -100 <= M[i][j] <= 100。
對于所有評測用例,1 <= n, m <= 1000, -1000 <= M[i][j] <= 1000。
解法一
原文鏈接:1.0219——2021年第十二屆藍橋杯第三場校模擬賽
package simulationMatch_12_2021_3;import java.util.Scanner;public class _08H {static int total = 0, n, m;static int[][] v;static int r = 0, c = 0, d = Integer.MAX_VALUE;public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();v = new int[n][m];for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {v[i][j] = sc.nextInt();total += v[i][j];}}int[][] dp = new int[n + 1][m + 1];for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + v[i - 1][j - 1];check(dp[i][j], i, j);}}System.out.println(r + " " + c);}public static void check(int x, int i, int j) {if (Math.abs(2 * x - total) < d || Math.abs(2 * x - total) == d && i * j < r * c) {r = i;c = j;d = Math.abs(2 * x - total);}} }九、試題I
問題描述
給定一張圖片,由 n 行 m 列像素組成,每個像素由一個范圍在 0 到 255 的整數表示。
例如,下面是一張 4 行 7 列的圖片。
8 232 229 23 21 10 247
25 252 238 17 241 9 245
1 243 251 32 236 31 253
13 5 255 8 13 24 11
對于每個像素,請找出以這個像素為中心的3行3列中最亮(數值最大)的像素值。
例如,第 2 行第 2 列像素值為 252,而它周圍 8 個像素都沒有它亮,因此第 2 行第 2 列對應的值為 252。
第 3 行第 2 列對應的值為255。
第 1 行第 1 列為中心不足 3 行 3 列,最大值為 252。
將每個像素對應的值寫成上面圖片的樣子,得到:
252 252 252 241 241 247 247
252 252 252 251 241 253 253
252 255 255 255 241 253 253
243 255 255 255 236 253 253
輸入格式
輸入第一行包含兩個整數 n, m,分別表示圖片的行數和列數。
接下來 n 行,每行 m 個整數,表示一個像素。
輸出格式
輸出 n 行,每行 m 個整數,表示以每個像素為中心的3行3列中最亮的像素值。
樣例輸入
4 7
8 232 229 23 21 10 247
25 252 238 17 241 9 245
1 243 251 32 236 31 253
13 5 255 8 13 24 11
樣例輸出
252 252 252 241 241 247 247
252 252 252 251 241 253 253
252 255 255 255 241 253 253
243 255 255 255 236 253 253
數據規模和約定
對于所有評測用例,圖片的行數和列數均不超過 100,每個像素的值為 0 到 255 之間的整數。
解法一
求巨佬支招!
九、試題I(2)
時間限制: 3.0s 內存限制: 512.0MB 本題總分:25 分
【問題描述】
雜貨鋪老板一共有N件物品,每件物品具有ABC三種屬性中的一種或多種。從雜貨鋪老板處購得一件物品需要支付相應的代價。
現在你需要計算出如何購買物品,可以使得ABC三種屬性中的每一種都在至少一件購買的物品中出現,并且支付的總代價最小。
【輸入格式】
輸入第一行包含一個整數N。
以下N行,每行包含一個整數C和一個只包含"ABC"的字符串,代表購得該物品的代價和其具有的屬性。
【輸出格式】
輸出一個整數,代表最小的代價。如果無論如何湊不齊ABC三種屬性,輸出-1。
【樣例輸入】
5
10 A
9 BC
11 CA
4 A
5 B
【樣例輸出】
13
【評測用例規模與約定】
對于50%的評測用例,1 <= N <= 20
對于所有評測用例,1 <= N <= 1000, 1 <= C <= 100000
解法一
原文鏈接:1.0219——2021年第十二屆藍橋杯第三場校模擬賽
package simulationMatch_12_2021_3;//這種寫法更簡單同時效率更高 import java.util.Arrays; import java.util.Scanner;public class _09I2 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[] dp = new int[7 + 1]; // 模擬二進制,三種屬性C、B、A,讓它們分別代表4、2、1,即1<<2、1<<1、1<<0(注1<<n是位運算,不會的請先百度),當i==5時,dp[i]表示擁有CA屬性時代價最小Arrays.fill(dp, Integer.MAX_VALUE); // 7(十進制)==111(二進制)==CBA,故最終dp[7]就表示同時擁有ABC屬性時代價最小for (int i = 0; i < n; ++i) {int c = sc.nextInt(), v = 0; // v是用來記錄當前物品有哪幾種屬性char[] ch = sc.next().toCharArray();for (int j = 0; j < ch.length; ++j)v |= 1 << (ch[j] - 'A');for (int j = 1; j < dp.length; ++j) { // j從1到7,分別表示A、B、C、BA、CA、CB、CBA 不會 &(與運算)和 |(或運算)滴,請先百度if ((j & v) != v && dp[j] != Integer.MAX_VALUE && c + dp[j] < dp[v | j]) // 假設j==5,v==4,則v中擁有的屬性,j也有,所以j沒必要與v進行組合dp[v | j] = c + dp[j]; // 當dp[j] == Integer.MAX_VALUE時,代表還沒有j這種組合;}dp[v] = Math.min(dp[v], c);}System.out.println(dp[7] == Integer.MAX_VALUE ? -1 : dp[7]);} }十、試題J
問題描述
給定一個序列 (a_1, a_2, ..., a_n), 它的一個上升子序列是指從序列中取出一些元素,按照原來的順序排列后,是單調遞增的序列。
例如,對于序列 (3, 2, 7, 6, 7),取出下標為 2, 4, 5 的元素 a_2, a_4, a_5,即 2, 6, 7,是一個上升子序列。
在這個序列中,有 7 個長度為 2 的上升子序列,例如
1. 下標 1, 3 對應的 3, 7;
2. 下標 1, 4 對應的 3, 6;
3. 下標 1, 5 對應的 3, 7;
4. 下標 2, 3 對應的 2, 7;
5. 下標 2, 4 對應的 2, 6;
6. 下標 2, 5 對應的 2, 7;
7. 下標 4, 5 對應的 6, 7。
注意,可能有下標不同但對應數值相同的上升子序列,他們應當算成不同的上升子序列。
給定序列,請問序列中一共有多少個長度為 k 的上升子序列。
輸入格式
輸入第一行包含兩個整數 n, k,表示序列的長度和上升子序列的長度。
第二行包含 n 個整數 a_1, a_2, ..., a_n,表示給定的序列。
輸出格式
輸出一行,包含一個整數,表示長度為 k 的上升子序列的數量,答案可能很大,請輸出答案除以 1000007 的余數。
樣例輸入
5 2
3 2 7 6 7
樣例輸出
7
數據規模和約定
對于 30% 的評測用例,1 <= n <= 20, 0 <= a_i <= 100。
對于 50% 的評測用例,1 <= n <= 100, 0 <= a_i <= 1000。
對于所有評測用例,1 <= n <= 1000, 1 <= k <= 10, 0 <= a_i <= 10000。
解法一
原文鏈接:1.0219——2021年第十二屆藍橋杯第三場校模擬賽
package simulationMatch_12_2021_3;import java.util.Scanner; import java.util.Arrays;public class _10J {static int n, k, MOD = 1000007;static int[] r;public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();k = sc.nextInt();r = new int[n];for (int i = 0; i < n; ++i) {r[i] = sc.nextInt();}int[][] dp = new int[n][k + 1];for (int i = 0; i < n; ++i) {dp[i][1] = 1;}for (int i = 1; i < n; ++i) {for (int j = 0; j < i; ++j) {if (r[i] > r[j]) {for (int t = 1; t <= k; ++t) {if (dp[j][t - 1] != 0) {dp[i][t] = (dp[i][t] + dp[j][t - 1]) % MOD;}}}}}int ans = 0;for (int i = 0; i < n; ++i) {ans = (ans + dp[i][k]) % MOD;}System.out.println(ans);} }小結
難!
總結
以上是生活随笔為你收集整理的2021年 第12届 蓝桥杯 第3次模拟赛真题详解及小结【Java版】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++阶段01笔记01【C++初识(第一
- 下一篇: C++阶段01笔记02【数据类型(整型、