2014年第五屆藍橋杯javaB組 試題 答案 解析

1.武功祕籍

  • 小明到X山洞探險,撿到一本有破損的武功祕籍(2000多頁!固然是僞造的)。他注意到:書的第10頁和第11頁在同一張紙上,但第11頁和第12頁不在同一張紙上。
  • 小明只想練習該書的第81頁到第92頁的武功,又不想帶着整本書。請問他至少要撕下多少張紙帶走?
  • 這是個整數,請經過瀏覽器提交該數字,不要填寫任何多餘的內容。

熱身題html

public class Main {
	public static void main(String[] args) {
		for(int i = 10; i < 100; i += 2){
			System.out.println("本頁包括 : " + i + " 和 " + (i + 1));
		}
	}
}
答案 : 7

2.切面條

  • 一根高筋拉麪,中間切一刀,能夠獲得2根麪條。
  • 若是先對摺1次,中間切一刀,能夠獲得3根麪條。
  • 若是連續對摺2次,中間切一刀,能夠獲得5根麪條。
  • 那麼,連續對摺10次,中間切一刀,會獲得多少麪條呢?
  • 答案是個整數,請經過瀏覽器提交答案。不要填寫任何多餘的內容。

我把它當作是一道考二叉樹的題. 考的是第k層的結點個數, 可是最後要加1, 這個1能夠理解成頭結點. 拿張紙條切一切和二叉樹的圖對比一下便可.java

public class Main {
	public static void main(String[] args) {
		System.out.println(getNoodles(10));
	}
	
	public static int getNoodles(int n){
		return (1 << n) + 1;
	}
}
答案 : 1025

3. 猜字母

  • 把abcd...s共19個字母組成的序列重複拼接106次,獲得長度爲2014的串。
  • 接下來刪除第1個字母(即開頭的字母a),以及第3個,第5個等全部奇數位置的字母。
  • 獲得的新串再進行刪除奇數位置字母的動做。如此下去,最後只剩下一個字母,請寫出該字母。
  • 答案是一個小寫字母,請經過瀏覽器提交答案。不要填寫任何多餘的內容。

 

個人思路是先拼接出字符串, 而後經過數組原地調整的方式不斷縮字符串, 相似2013年第八題幸運數.c++

public class Main {

	public static void main(String[] args) {
		String s = "";
		for(int i = 0; i < 106; i++){
			s += "abcdefghijklmnopqrs";
		}
		char[] arr = s.toCharArray();
		int len = arr.length;
		int index = 0;
		while(len != 1){
			for(int i = 0; i < len; i++){
				if(((i + 1) & 1) == 0){
					arr[index++] = arr[i];
				}
			}
			System.out.println(arr[0]);//把縮完後每一次的開頭都打印出來, 以便檢驗.
			index = 0;
			len = len / 2;
		}
	}
}
答案 : q

4.大衍數列

  • 中國古代文獻中,曾記載過「大衍數列」, 主要用於解釋中國傳統文化中的太極衍生原理。
  • 它的前幾項是:0、二、四、八、十二、1八、2四、3二、40、50 ...
  • 其規律是:對偶數項,是序號平方再除2,奇數項,是序號平方減1再除2。
  • 如下的代碼打印出了大衍數列的前 100 項。
for(int i=1; i<100; i++)
{
	if(________________)  //填空
		System.out.println(i*i/2);
	else
		System.out.println((i*i-1)/2);
}
  • 請填寫劃線部分缺失的代碼。經過瀏覽器提交答案。
  • 注意:不要填寫題面已有的內容,也不要填寫任何說明、解釋文字。

 

判斷一個數是否是偶數算法

答案 : (i & 0) == 0

 


5.圓周率

  • 數學發展歷史上,圓周率的計算曾有許多有趣甚至是傳奇的故事。其中許多方法都涉及無窮級數。
  • 圖1.png中所示,就是一種用連分數的形式表示的圓周率求法。
  • 下面的程序實現了該求解方法。實際上數列的收斂對x的初始值 並不敏感。
  • 結果打印出圓周率近似值(保留小數點後4位,並不必定與圓周率真值吻合)。
double x = 111; 
	for(int n = 10000; n>=0; n--){
		int i = 2 * n + 1;
		x = 2 + (i*i / x);
	}
	
	System.out.println(String.format("%.4f", ______________));

<html> <img src="http://m.qpic.cn/psb?/V11njlod3LYfx7/eg.fjfObLv6lNDqbEaqOn4vZDFg73nRWowZJqkCiOR8!/b/dL8AAAAAAAAA&bo=pwHzAKcB8wADCSw!&rf=viewer_4" alt="" /> </html>數組

根據題目中的代碼能夠推算出x等於2+一大坨分數, 而後便可經過解方程獲得圓周率.瀏覽器

<html> <img src="http://m.qpic.cn/psb?/V11njlod3LYfx7/bOi6RTyWt92JCJHSt2sdqTy4eRz1sD0JHZ.NN.gadB8!/b/dLgAAAAAAAAA&bo=TwGLAQAAAAADB.Y!&rf=viewer_4"/> </html>測試

答案 : 4/(x-1)

 


6.奇怪的分式

  • 上小學的時候,小明常常本身發明新算法。一次,老師出的題目是:
  • 1/4 乘以 8/5
  • 小明竟然把分子拼接在一塊兒,分母拼接在一塊兒,答案是:18/45 (參見圖1.png)
  • 老師剛想批評他,轉念一想,這個答案湊巧也對啊,真是見鬼!
  • 對於分子、分母都是 1~9 中的一位數的狀況,還有哪些算式能夠這樣計算呢?
  • 請寫出全部不一樣算式的個數(包括題中舉例的)
  • 顯然,交換分子分母后,例如:4/1 乘以 5/8 是知足要求的,這算作不一樣的算式。
  • 但對於分子分母相同的狀況,2/2 乘以 3/3 這樣的類型太多了,不在計數之列!
  • 注意:答案是個整數(考慮對稱性,確定是偶數。請經過瀏覽器提交。不要書寫多餘的內容。

<html> <img src="http://m.qpic.cn/psb?/V11njlod3LYfx7/*gqAIs5TXPItcPmUCZRQBw0AAhhqlEHCSVYHIg0*p3g!/b/dDQBAAAAAAAA&bo=KQG*AAAAAAADB7U!&rf=viewer_4" /> <!--在這裏插入內容--> </html>this

 

解題思路: 按照題目的步驟判斷兩個結果是否相等, 兩個結果分別用4個變量湊出, 注意判斷相等的時候使用浮點類型.spa

public class Main {
	public static void main(String[] args) {
		int res = 0;
		float num1 = 0;
		float num2 = 0;
		for(float a = 1; a <= 9; a++){
			for(float b = 1; b <= 9; b++){
				if(b == a) continue;
				for(float c = 1; c <= 9; c++){
					for(float d = 1; d <= 9; d++){
						if(c == d) continue;
						
						num1 = (a * 10 + c) / (b * 10 + d);
						num2 = (a * c) / (b * d);
						if(num1 == num2){
							res++;
						}
					}
				}
			}
		}
		System.out.println(res);
	}
}
答案 : 14

 


7.撲克序列

  • A A 2 2 3 3 4 4, 一共4對撲克牌。請你把它們排成一行。
  • 要求:兩個A中間有1張牌,兩個2之間有2張牌,兩個3之間有3張牌,兩個4之間有4張牌。
  • 請填寫出全部符合要求的排列中,字典序最小的那個。
  • 例如:22AA3344 比 A2A23344 字典序小。固然,它們都不是知足要求的答案。
  • 請經過瀏覽器提交答案。「A」必定不要用小寫字母a,也不要用「1」代替。字符間必定不要留空格。

 

解題思路: 首先經過全排列找到全部的狀況, 而後在全部狀況中篩選符合題目要求的字符串. 最後比較符合要求的字符串的字典序, 經過比較器比較(各個語言都有).調試

public class Main {
	
	public static LinkedList<String> qua = new LinkedList<String>();
	
	public static void main(String[] args) {
		String str = "AA223344";
		process(str.toCharArray(), 0);//全排列
		ArrayList<String> preList = new ArrayList<String>();
		//拿到符合要求的序列
		for(String s : qua){
			if(isOk(s)){
				preList.add(s);
			}
		}
		//按照字典序排序
		Collections.sort(preList, new StringComparator());
		System.out.println(preList.get(0));
	}
	
	public static class Index{
		public int first;
		public int last;
		public Index(int first){
			this.first = first;
		}
	}
	
	public static boolean isOk(String s){
		char[] arr = s.toCharArray();
		HashMap<Character, Index> map = new HashMap<Character, T7.Index>();
		for(int i = 0; i < arr.length; i++){
			if(!map.containsKey(arr[i])){
				map.put(arr[i], new Index(i));
			}else{
				Index index = map.get(arr[i]);
				index.last = i;
				map.put(arr[i], index);
			}
		}
		Index a = map.get('A');
		if(a.last - a.first - 1 != 1){
			return false;
		}
		Index b = map.get('2');
		if(b.last - b.first - 1 != 2){
			return false;
		}
		Index c = map.get('3');
		if(c.last - c.first - 1 != 3){
			return false;
		}
		Index d = map.get('4');
		if(d.last - d.first - 1 != 4){
			return false;
		}
		return true;
	}
	
	public static void process(char[] ori, int index){
		if(index == ori.length){
			qua.add(String.valueOf(ori));
			return;
		}
		for(int i = index; i < ori.length; i++){
			swap(ori, index, i);
			process(ori, index + 1);
			swap(ori, index, i);
		}
	}
	
	public static class StringComparator implements Comparator<String> {
		public int compare(String s1, String s2) {
			return s1.compareTo(s2);
		}
	}
	
	public static void swap(char[] ori, int i, int j){
		char temp = ori[i];
		ori[i] = ori[j];
		ori[j] = temp;
	}
}

答案: 2342A3A4

 


8.分糖果

  • 有n個小朋友圍坐成一圈。老師給每一個小朋友隨機發偶數個糖果,而後進行下面的遊戲:
  • 每一個小朋友都把本身的糖果分一半給左手邊的孩子。
  • 一輪分糖後,擁有奇數顆糖的孩子由老師補給1個糖果,從而變成偶數。
  • 反覆進行這個遊戲,直到全部小朋友的糖果數都相同爲止。
  • 你的任務是預測在已知的初始糖果情形下,老師一共須要補發多少個糖果。
【格式要求】

程序首先讀入一個整數N(2<N<100),表示小朋友的人數。
接着是一行用空格分開的N個偶數(每一個偶數不大於1000,不小於2)
要求程序輸出一個整數,表示老師須要補發的糖果數。

例如:輸入
3
2 2 4
程序應該輸出:
4

資源約定:
峯值內存消耗(含虛擬機) < 256M
CPU消耗  < 1000ms
  • 請嚴格按要求輸出,不要多此一舉地打印相似:「請您輸入...」 的多餘內容。
  • 全部代碼放在同一個源文件中,調試經過後,拷貝提交該源碼。
  • 注意:不要使用package語句。不要使用jdk1.7及以上版本的特性。
  • 注意:主類的名字必須是:Main,不然按無效代碼處理。

 

解題思路: 按照題目一路寫代碼

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int[] arr = new int[sc.nextInt()];//每一個孩子有多少糖
		int[] tempCandy = new int[arr.length];//定義一個輔助數組保存每一個孩子給左邊孩子給多少糖
		for(int i = 0; i < arr.length; i++){
			arr[i] = sc.nextInt();
		}
		
		int left = 0;
		int res = 0;
		boolean equal = false;
        //只要孩子的糖不相等就進行循環
		while(!equal){
			//每一個孩子付出糖
			for(int i = 0; i < arr.length; i++){
				tempCandy[i] = arr[i] / 2;
				arr[i] /= 2;
			}
			//每一個孩子接收糖
			for(int i = 0; i < arr.length; i++){
				left = getLeftIndex(i, arr);
				arr[left] += tempCandy[i];
			}
			//老師發糖平衡天下
			for(int i = 0; i < arr.length; i++){
				if((arr[i] & 1) != 0){
					arr[i] += 1;
					res++;
				}
			}
			//看看這一輪平了沒有
			boolean isEqual = true;
			for(int i = 1; i < arr.length; i++){
				if(arr[i] != arr[i - 1]){
					isEqual = false;
					break;
				}
			}
			equal = isEqual ? true : false;
		}
		System.out.println(res);
	}
	
	public static int getLeftIndex(int index, int[] arr){
		return index == 0 ? arr.length - 1 : index - 1;
	}
}

 


9.地宮取寶

  • X 國王有一個地宮寶庫。是 n x m 個格子的矩陣。每一個格子放一件寶貝。每一個寶貝貼着價值標籤。
  • 地宮的入口在左上角,出口在右下角。
  • 小明被帶到地宮的入口,國王要求他只能向右或向下行走。
  • 走過某個格子時,若是那個格子中的寶貝價值比小明手中任意寶貝價值都大,小明就能夠拿起它(固然,也能夠不拿)。
  • 當小明走到出口時,若是他手中的寶貝剛好是k件,則這些寶貝就能夠送給小明。
  • 請你幫小明算一算,在給定的局面下,他有多少種不一樣的行動方案能得到這k件寶貝。
數據格式】

輸入一行3個整數,用空格分開:n m k (1<=n,m<=50, 1<=k<=12)

接下來有 n 行數據,每行有 m 個整數 Ci (0<=Ci<=12)表明這個格子上的寶物的價值

要求輸出一個整數,表示正好取k個寶貝的行動方案數。該數字可能很大,輸出它對 1000000007 取模的結果。

例如,輸入:
2 2 2
1 2
2 1
程序應該輸出:
2

再例如,輸入:
2 3 2
1 2 3
2 1 5
程序應該輸出:
14

資源約定:
峯值內存消耗(含虛擬機) < 256M
CPU消耗  < 2000ms

思路:

  1. 遞歸的邏輯是: 若是當前格子的寶藏的值比手頭上寶貝的最大值大, 就能夠取走, 而且能夠向右或向下走.
  2. 因此若是能夠拿走寶貝, 就有4種狀況; 若是不能夠拿走寶貝就只有兩種狀況.見代碼
  3. 若是隻是這樣寫的話, 樣本量大的時候會超時, 由於最多要連續走100個格子, 每一個格子算2種選擇, 2的100次方是很可怕的.
  4. 當以相同狀態走過同一個格子的時候, 好比說x=2,y=2,max=4,cur=2, 若是以前經歷過這樣的情況, 就能夠直接返回以前的結果了, 這裏能夠用一個數組進行記憶.

踩坑:

  1. 開始時, 我沒有初始化記憶數組, 數組的每一個格子都是0, 最後沒有節省時間, 由於不少格子上記錄的就是0, 只有0種取法.
  2. 沒有留意題目種對結果取餘的告誡, 只在最後return res以前取餘數. 最終有3個測試用例過不了, 由於每次遞歸的結果都有可能超過1000000007, 最後才進行取餘在樣本量極大的狀況下是會出錯的.
public class T9 {
	
	public static int n;
	public static int m;
	public static int k;
	public static int[][][][] dp = new int[50][50][15][15];//用於記憶搜索
	public static int[][] arr = new int[50][50];
	
	public static void main(String[] args) {
		//處理輸入
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		k = sc.nextInt();
		for(int i = 0; i < n; i++){
			for(int j = 0; j < m; j++){
				arr[i][j] = sc.nextInt();
			}
		}
		initDp();//初始化記憶數組,不能用java初始的0值,由於不少格子只有0種可能, 會形成重複搜索. 
		System.out.println(process(arr, 0, 0, -1, 0));//寶藏的最小值爲0, 因此初始的max值爲-1
	}
	
	public static int process(int[][] arr, int x, int y, int max, int cur){
		if(dp[x][y][max + 1][cur] != -1){//max初始爲-1,爲防止越界填入max+1
			return dp[x][y][max + 1][cur];
		}
		if(x >= n || y >= m || cur > k){
			return 0;
		}
		int value = arr[x][y];
		if(x == n - 1 && y == m - 1){
			if(cur == k || (value > max && cur == k - 1)){
				return 1;
			}
			return 0;
		}
		int res = 0;
		if(value > max){//若是寶藏大於當前手上的最大值, 就能夠拿走.
			res += process(arr, x, y + 1, value, cur + 1);//每次遞歸完對結果取模, 不然數據量大的時候會出錯.
			res %= 1000000007;
			res += process(arr, x + 1, y, value, cur + 1);
			res %= 1000000007;
		}
		//不拿走
		res += process(arr, x, y + 1, max, cur);
		res %= 1000000007;
		res += process(arr, x + 1, y, max, cur);
		res %= 1000000007;
		
		dp[x][y][max + 1][cur] = res;
		return res;
	}
	
	public static void initDp(){
		for(int i = 0; i < 50; i++){
			for(int j = 0; j < 50; j++){
				for(int k = 0; k < 15; k++){
					for(int l = 0; l < 15; l++){
						dp[i][j][k][l] = -1;
					}
				}
			}
		}
	}
}

 


10.矩陣翻硬幣

  • 小明先把硬幣擺成了一個 n 行 m 列的矩陣。
  • 隨後,小明對每個硬幣分別進行一次 Q 操做。
  • 對第x行第y列的硬幣進行 Q 操做的定義:將全部第 i*x 行,第 j*y 列的硬幣進行翻轉。
  • 其中i和j爲任意使操做可行的正整數,行號和列號都是從1開始。
  • 當小明對全部硬幣都進行了一次 Q 操做後,他發現了一個奇蹟——全部硬幣均爲正面朝上。
  • 小明想知道最開始有多少枚硬幣是反面朝上的。因而,他向他的好朋友小M尋求幫助。
  • 聰明的小M告訴小明,只須要對全部硬幣再進行一次Q操做,便可恢復到最開始的狀態。然而小明很懶,不肯意照作。因而小明但願你給出他更好的方法。幫他計算出答案。

-【數據格式】

  • 輸入數據包含一行,兩個正整數 n m,含義見題目描述。
  • 輸出一個正整數,表示最開始有多少枚硬幣是反面朝上的。
【樣例輸入】
2 3

【樣例輸出】
1

【數據規模】
對於10%的數據,n、m <= 10^3;
對於20%的數據,n、m <= 10^7;
對於40%的數據,n、m <= 10^15;
對於10%的數據,n、m <= 10^1000(10的1000次方)。

資源約定:
峯值內存消耗(含虛擬機) < 256M
CPU消耗  < 2000ms

思路

  • 用題目中的操做只能過10%的數據.
  • 首先要理解Q操做的定義:將全部第i*x 行,第j*y 列的硬幣進行翻轉. 也就是說如今定位的硬幣座標是x,y, 是x的倍數的行都要翻, 是y的倍數的列也要翻.
  • 假設有9行9列的硬幣, 對座標(9,9)的硬幣target進行分析. 第一行的硬幣命中了target的行, 假如來到第一列, 那麼target就要翻一下; 假如來到了第1行, 第3列, target也要翻一下.
  • 這麼一來, 一個硬幣就要翻 (x的因子數 * y的因子數) 那麼屢次
  • 若是一個數一共翻了奇數次, 它一開始就是反面朝上的.
  • 因爲只有奇數相乘才能獲得奇數. 因此要求x的因子數和y的因子數都必須是奇數.
  • 什麼數的因子數是奇數? 只有平方數的因子數是奇數, 由於普通數的因子數都是一對一對的.
  • 因此如今的問題轉化成求x中有多少個平方數y中有多少個平方數.
  • 平方數有: 1, 4, 9...
  • 根據數學規律, 求一個數包含多少個平方數只須要將該數開方後向下取整便可, 好比說10開方取整後得3, 它一共包含3個平方數.
  • 因爲數據的取值範圍是10^1000, 不能用已有的基本數據類型進行開放, 因此接下來的問題轉化爲如何對一個大數進行開方.
  • 首先要知道大數有多少位, 好比兩位數16開方後得一位數4, 3位數100開方後得2位數10. 總結出結果是若是一個數的位數是偶數, 開方後獲得的數的位數也是偶數, 若是是奇數, 得出的結果有原數位數 / 2 + 1 這麼多位.
  • 知道結果有多少位後, 就能夠試數了. 假設結果是3位, 先假設爲000, 而後從頭開始試100, 試110, 試111, 試112...直到得出平方數.
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String n = sc.next();
		String m = sc.next();
		System.out.println(sqrt(n).multiply(sqrt(m)));
	}
	
	public static BigInteger sqrt(String num){
		int numLen = num.length();//要開方的數字位數
		int resLen = (numLen & 1) == 0 ? numLen / 2 : numLen / 2 + 1;//開方後數字的位數
		char[] arr = new char[resLen];//用於嘗試結果的數組
		Arrays.fill(arr, '0');
		BigInteger target = new BigInteger(num);
		for(int pos = 0; pos < resLen; pos++){
			for(char i = '1'; i <= '9'; i++){
				arr[pos] = i;
				BigInteger pow = new BigInteger(String.valueOf(arr)).pow(2);
				if(pow.compareTo(target) == 1){
					arr[pos] -= 1;
					break;
				}
			}
		}
		return new BigInteger(String.valueOf(arr));
	}
}
相關文章
相關標籤/搜索