2016年第七届蓝桥杯javaB组 试题 答案 解析
1.煤球數目
- 有一堆煤球,堆成三角棱錐形。具體:
- 第一層放1個,
- 第二層3個(排列成三角形),
- 第三層6個(排列成三角形),
- 第四層10個(排列成三角形),
- ....
- 如果一共有100層,共有多少個煤球?
- 請填表示煤球總數目的數字。
- 注意:你提交的應該是一個整數,不要填寫任何多余的內容或說明性文字。
答案: 171700
?
2.生日蠟燭
- 某君從某年開始每年都舉辦一次生日party,并且每次都要吹熄與年齡相同根數的蠟燭。
- 現在算起來,他一共吹熄了236根蠟燭。
- 請問,他從多少歲開始過生日party的?
- 請填寫他開始過生日party的年齡數。
- 注意:你提交的應該是一個整數,不要填寫任何多余的內容或說明性文字。
答案: 26
?
3.湊算式
B DEF A + --- + ------- = 10C GHI- 這個算式中A~I代表1~9的數字,不同的字母代表不同的數字。
- 比如:
- 6+8/3+952/714 就是一種解法,
- 5+3/1+972/486 是另一種解法。
- 這個算式一共有多少種解法?
答案: 29
?
4. 分小組
- 9名運動員參加比賽,需要分3組進行預賽。
- 有哪些分組的方案呢?
- 我們標記運動員為 A,B,C,... I
- 下面的程序列出了所有的分組方法。
仔細閱讀代碼,填寫劃線部分缺少的內容。
答案: s + " " + (char)(i + 'A') + (char)(j + 'A') + (char)(k + 'A') + " " + remain(a)
?
5.抽簽
- X星球要派出一個5人組成的觀察團前往W星。
- 其中:
- A國最多可以派出4人。
- B國最多可以派出2人。
- C國最多可以派出2人。
- ....
- 那么最終派往W星的觀察團會有多少種國別的不同組合呢?
- 下面的程序解決了這個問題。
- 數組a[] 中既是每個國家可以派出的最多的名額。
- 程序執行結果為:
仔細閱讀代碼,填寫劃線部分缺少的內容。
答案: f(a, k + 1, n - i, s2);
?
6.方格填數
- 如下的10個格子
- 填入0~9的數字。要求:連續的兩個數字不能相鄰。
(左右、上下、對角都算相鄰) - 一共有多少種可能的填數方案?
- 請填寫表示方案數目的整數。
這道題的遞歸策略類似八皇后問題, 也就說當來到第一個格子后, 下一個要填的數不是連接著下一個位置的, 也就是說每個位置要填的數字來自于整個樣本, 而且要注意回溯, 保證其他遞歸過程沒有出錯.
public class Six {public static int[][] dp = new int[5][6];public static int[] arr = new int[10];public static int res = 0;public static void main(String[] args) {initDp();process(1, 2);System.out.println(res);}public static void process(int x, int y){if(x == 3 && y == 4){res++;return;}for(int n = 0; n <= 9; n++){if(arr[n] == 0 && canFill(x, y, n)){dp[x][y] = n;arr[n] = 1;if(y == 4){process(x + 1, 1);}else{process(x, y + 1);}arr[n] = 0;dp[x][y] = -11;}}}public static boolean canFill(int x, int y, int n){boolean ans = true;for(int i = -1; i <= 1; i++){for(int j = -1; j <= 1; j++){if(i == 0 && j == 0) continue;if(Math.abs(dp[x + i][y + j] - n) <= 1){ans = false;}}}return ans;}public static void initDp(){for(int i = 0; i < 5; i++){for(int j = 0; j < 6; j++){dp[i][j] = -11;}}} }答案: 1580
?
7.剪郵票
- 如【圖1.jpg】, 有12張連在一起的12生肖的郵票
- 現在你要從中剪下5張來,要求必須是連著的
- (僅僅連接一個角不算相連)
- 比如,【圖2.jpg】,【圖3.jpg】中,粉紅色所示部分就是合格的剪取。
- 請你計算,一共有多少種不同的剪取方法。
- 請填寫表示方案數目的整數。
首先通過5層for循環枚舉選出5數, 難點在于判斷這5個數是否是相連的, 可以利用圖中標有編號的特性進行判斷. 可以直觀地看到一個數上面聯通的數可-4得到, 下面的數可+4得到, 同理左邊是-1, 右邊是+1. 但是, 有特殊情況, 比如4+1為5, 理論上4的右邊是5, 但是由于換行的原因, 4和5不是聯通的. 但是這個方法是好的, 可以通過修改圖中的編號繼續使用這個方法.
可以把圖改成: 1 2 3 4 6 7 8 9 10 11 12 13 public class Seven {public static int res = 0;public static int[] arr = {1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14};public static int[] p = new int[5];public static boolean[] visit = new boolean[5];public static int[] c = {5, -5, 1, -1};public static void main(String[] args) {for(int a = 0; a < 12; a++){for(int b = a + 1; b < 12; b++){for(int c = b + 1; c < 12; c++){for(int d = c + 1; d < 12; d++){for(int e = d + 1; e < 12; e++){p[0] = arr[a];p[1] = arr[b];p[2] = arr[c];p[3] = arr[d];p[4] = arr[e];process(0);boolean flag = true;for(int i = 0; i < 5; i++){if(!visit[i]){flag = false;}}if(flag){res++;}cleanVisit();}}}}}System.out.println(res);}public static void process(int n){for(int i = 0; i < 4; i++){int t = p[n] + c[i];if(t < 1 || t > 14 || t == 5 || t == 10){continue;}for(int j = 0; j < 5; j++){if(!visit[j] && p[j] == t){visit[j] = true;process(j);}}}}public static void cleanVisit(){for(int i = 0; i < 5; i++){visit[i] = false;}} }答案: 116
?
8.四平方和
- 四平方和定理,又稱為拉格朗日定理:
- 每個正整數都可以表示為至多4個正整數的平方和。
- 如果把0包括進去,就正好可以表示為4個數的平方和。
- 比如:
- 5 = 0^2 + 0^2 + 1^2 + 2^2
- 7 = 1^2 + 1^2 + 1^2 + 2^2
- (^符號表示乘方的意思)
- 對于一個給定的正整數,可能存在多種平方和的表示法。
- 要求你對4個數排序:
- 0 <= a <= b <= c <= d
- 并對所有的可能表示法按 a,b,c,d 為聯合主鍵升序排列,最后輸出第一個表示法
- 程序輸入為一個正整數N (N<5000000)
- 要求輸出4個非負整數,按從小到大排序,中間用空格分開
這道題是常規的暴力枚舉題, 難在如何降低時間復雜度跑過所有的用例, 如果a, b, c, d每個數都窮舉以便, 按照最大的輸入5000000, 每個數要枚舉的次數為10^3級, 一共就是10^12. 太大了, 會超時. 為了能減少次數, 把枚舉分成兩半, 一半的數據是a * a + b * b, 這一半的數據用哈希表存儲, 另外一半的數據是c * c + d * d = n - a * a + b * b. 這樣能把枚舉的規模縮小一半.
public class Eight {static HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();for(int c = 0; c * c <= n / 2; c++){for(int d = c; c * c + d * d <= n; d++){if(!map.containsKey(c * c + d * d)){map.put(c * c + d * d, c);}}}for(int a = 0; a * a <= n / 4; a++){for(int b = a; a * a + b * b <= n; b++){if(map.containsKey(n - a * a - b * b)){int c = map.get(n - a * a - b * b);int d = (int) Math.sqrt(n - a * a - b * b - c * c);System.out.println(a + " " + b + " " + c + " " + d);return;}}}}}?
9.取球博弈
- 兩個人玩取球的游戲。
- 一共有N個球,每人輪流取球,每次可取集合{n1,n2,n3}中的任何一個數目。
- 如果無法繼續取球,則游戲結束。
- 此時,持有奇數個球的一方獲勝。
- 如果兩人都是奇數,則為平局。
- 假設雙方都采用最聰明的取法,
- 第一個取球的人一定能贏嗎?
- 試編程解決這個問題。
- 輸入格式:
- 第一行3個正整數n1 n2 n3,空格分開,表示每次可取的數目 (0<n1,n2,n3<100)
- 第二行5個正整數x1 x2 ... x5,空格分開,表示5局的初始球數(0<xi<1000)
- 輸出格式:
- 一行5個字符,空格分開。分別表示每局先取球的人能否獲勝。
- 能獲勝則輸出+,
- 次之,如有辦法逼平對手,輸出0,
- 無論如何都會輸,則輸出-
思路
- 首先要明確每一局的情況, 假設一局有x個球, 取球情況的數組為n.
- 在每一局中, 某一方取球都會根據取球情況數組進行試探, 如上圖.
- 在每次遞歸中, 需要的參數有當前剩下的球, 我摸的球數, 對手摸的球數.
- 如何才能判斷一局的勝負? 在所有情況中, 只要對手輸過, 結果就是贏; 如果對手沒輸過, 但是平過, 結果就是平; 否則, 結果就是輸. (因為題目條件: 雙方都采取最聰明的辦法)
- 最大的難點在于在于遞歸的過程中, 不是每次都是我摸, 而是我摸一次, 對手摸一次, 這里恰好就是這種類型遞歸的魅力所在.
- 具體落實到代碼中
優化
- 作為編程大題, 如果不優化是過不了極端的數據樣本的.
- 這題可以用數組記錄重復出現的情況, 進行記憶型遞歸, 用空間換時間.
- 問題來了: me和you是不斷交換的, 怎樣才算是一種情況?
- 在base case中, 最后決定輸贏的, 不是你我手上有多少個球, 而是你我的球數的奇偶情況, 所以我們把每一種情況記錄為: 剩余的球數和雙方球數的奇偶情況.
?
10.壓縮變換
- 小明最近在研究壓縮算法。
- 他知道,壓縮的時候如果能夠使得數值很小,就能通過熵編碼得到較高的壓縮比。
- 然而,要使數值很小是一個挑戰。
- 最近,小明需要壓縮一些正整數的序列,這些序列的特點是,后面出現的數字很大可能是剛出現過不久的數字。對于這種特殊的序列,小明準備對序列做一個變換來減小數字的值。
- 變換的過程如下:
- 從左到右枚舉序列,每枚舉到一個數字,如果這個數字沒有出現過,剛將數字變換成它的相反數,如果數字出現過,則看它在原序列中最后的一次出現后面(且在當前數前面)出現了幾種數字,用這個種類數替換原來的數字。
- 比如,序列(a1, a2, a3, a4, a5)=(1, 2, 2, 1, 2)在變換過程為:
- a1: 1未出現過,所以a1變為-1;
- a2: 2未出現過,所以a2變為-2;
- a3: 2出現過,最后一次為原序列的a2,在a2后、a3前有0種數字,所以a3變為0;
- a4: 1出現過,最后一次為原序列的a1,在a1后、a4前有1種數字,所以a4變為1;
- a5: 2出現過,最后一次為原序列的a3,在a3后、a5前有1種數字,所以a5變為1。
- 現在,給出原序列,請問,按這種變換規則變換后的序列是什么。
按照題目的思路, 使用HashMap記錄數的下標, 使用HashSet記錄不同種的的數字, 時間復雜度O(N^2), 暴力做法能得30分.
public class Ten {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();long[] arr = new long[n];for(int i = 0; i < arr.length; i++){arr[i] = sc.nextInt();}long[] former = Arrays.copyOf(arr, arr.length);HashMap<Long, Integer> map = new HashMap<Long, Integer>();for(int i = 0; i < arr.length; i++){if(!map.containsKey(arr[i])){map.put(arr[i], i);arr[i] = -arr[i];}else{int types = getTypes(map.get(arr[i]), i, former);map.put(arr[i], i);arr[i] = types;}}for(int i = 0; i < arr.length; i++){System.out.print(arr[i] + " ");}}public static int getTypes(int begin, int last, long[] former){HashSet<Long> set = new HashSet<Long>();int index = begin + 1;while(index < last){set.add(former[index++]);}return set.size();} }優化
- 未完待續...
轉載于:https://www.cnblogs.com/tanshaoshenghao/p/10542723.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的2016年第七届蓝桥杯javaB组 试题 答案 解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: I/O:OutputStream
- 下一篇: 个人简介2