1. 程式人生 > 其它 >2014年第五屆藍橋杯省賽試題及詳解(Java本科C組)

2014年第五屆藍橋杯省賽試題及詳解(Java本科C組)

1. 猜年齡

小明帶兩個妹妹參加元宵燈會。別人問她們多大了,她們調皮地說:“我們倆的年齡之積是年齡之和的6倍”。小明又補充說:“她們可不是雙胞胎,年齡差肯定也不超過8歲啊。”

請你寫出:小明的較小的妹妹的年齡。
注意: 只寫一個人的年齡數字,請通過瀏覽器提交答案。

package 藍橋2014C組;

public class T1 {

	public static void main(String[] args) {

		for (int i = 1; i <= 50; i++) {// 迴圈小妹妹的年齡
			for (int j = i + 1; j <= i + 8; j++) {// 迴圈大妹妹的年齡
				if ((i * j == (i + j) * 6)) {
					System.out.print(i);
				}
			}
		}
	}
//10
}
//注意外層迴圈是小妹妹的年齡 大妹妹的年齡的起始值i+1 終止值是i+8

2. 等額本金

小明從銀行貸款3萬元。約定分24個月,以等額本金方式還款。
這種還款方式就是把貸款額度等分到24個月。每個月除了要還固定的本金外,還要還貸款餘額在一個月中產生的利息。
假設月利率是:0.005,即:千分之五。那麼,
第一個月,小明要還本金 1250, 還要還利息:30000 * 0.005,總計 1400
第二個月,本金仍然要還 1250, 但利息為:(30000-1250) * 0.005 總計 1393.75

請問:小明在第15個月,應該還款多少(本金和利息的總和)?

請把答案金額四捨五入後,保留兩位小數。注意:32.5,一定要寫為:32.50

通過瀏覽器提交答案,這是一個含有小數點和兩位小數的浮點數字。不要寫多餘內容(例如:多寫了“元”或新增說明文字)
public static void main(String[] args) {

		System.out.println((30000 - 1250 * 14) * 0.005 + 1250);
	}

3. 猜字母

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

import java.util.ArrayList;
import java.util.List;

//刪除第1個字母(即開頭的字母a),以及第3個,第5個等所有奇數位置的字母。
//得到的新串再進行刪除奇數位置字母的動作。如此下去,最後只剩下一個字母,請寫出該字母。
/*分析:
 * 1.先得到長為2014的串
 * 2.將串中的每個字元放到集合中
 * 3.不停地對處於奇數位的元素刪除,只剩下一個字母為止
 * 4. 奇數位就對應於下標為偶數 i=i+2
 *  			for(int i=0;i<list.size();i=i+2) {
 				list.remove(i);
 但若採用上述刪除:
 因為每刪除一個元素,list.size()減小,它後面的元素的下標會有變化,就不能夠確保它刪除的一定是原來位於奇數位的
 解決:
 先去將所有處於奇數位的進行標記一下,第一輪刪除時,將標記過的,進行刪除
 進入第二輪,再重新將所有處於奇數位的進行標記一下,
 */
public class T3 {

	public static void main(String[] args) {
		String string = "";
		for (int i = 0; i <= 106; i++) {
			string += "abcdefghijklmnopqrs";
		}
		// 2.將串中的每個字元放到集合中
		List<Character> list = new ArrayList<>();
		for (int i = 0; i < string.length(); i++) {
			list.add(string.charAt(i));
		}
		// 3.利用迴圈去刪除奇數位置的字母
		while (true) {
			// 死迴圈結束條件
			if (list.size() == 1) {
				System.out.println(list.get(0));
				break;
			}

//			for(int i=0;i<list.size();i=i+2) {
//				list.remove(i);
//			}
			// (1)做標記,將奇數位變成0
			for (int i = 0; i < list.size(); i = i + 2) {
				list.set(i,'0');
			}
			// (2)刪除元素內容為‘0’的元素
			for (int i = 0; i < list.size(); i++) {
				if (list.get(i) == '0') {
					list.remove(i);
				}
			}
		}
	}
//q
}

5.寫日誌

寫日誌是程式的常見任務。現在要求在 t1.log, t2.log, t3.log 三個檔案間輪流寫入日誌。也就是說第一次寫入t1.log,第二次寫入t2.log,... 第四次仍然寫入t1.log,如此反覆。

下面的程式碼模擬了這種輪流寫入不同日誌檔案的邏輯。

請填寫劃線部分缺失的程式碼。通過瀏覽器提交答案。

public class A
{
    private static int n = 1;
    
    public static void write(String msg)
    {
        String filename = "t" + n + ".log";
        n = ____________;
        System.out.println("write to file: " + filename + " " + msg);
    }
}

程式碼實現:

private static int n = 1;   
    public static void write(String msg)
    {
        String filename = "t" + n + ".log";
//        n = n==3?1:n+1;
          n=n%3+1;
        System.out.println("write to file: " + filename + " " + msg);
    }
 
	public static void main(String[] args) {
		write("text");
		write("text");
		write("text");
		write("text");
		write("text");
		write("text");
	}
/*
write to file: t1.log text
write to file: t2.log text
write to file: t3.log text
write to file: t1.log text
write to file: t2.log text
write to file: t3.log text*/
}//注意:此題中的n是全域性變數   n = n==3?1:n+1;  和  n=n%3+1;

6.李白打酒

話說大詩人李白,一生好飲。
一天,他提著酒壺,從家裡出來,酒壺中有酒2鬥。他邊走邊唱:

無事街上走,提壺去打酒。
逢店加一倍,遇花喝一斗。

這一路上,他一共遇到店5次,遇到花10次,已知最後一次遇到的是花,他正好把酒喝光了。 

請你計算李白遇到店和花的次序,可以把遇店記為a,遇花記為b。則:babaabbabbabbbb 就是合理的次序。像這樣的答案一共有多少呢?請你計算出所有可能方案的個數(包含題目給出的)。

注意:通過瀏覽器提交答案。答案是個整數。不要書寫任何多餘的內容。

程式碼實現:

先來個簡化版的:(與2013年的上臺階十分相似)

李白每走一步可能遇到店,也有可能遇到花,若李白一共走三步,求所有他遇到店和花的次序序列。

第一步:遇見花或者店

若花,第二步遇見花或者店

依次選下去,每一次兩種選擇,直到走3步

static char[] meet = new char[3];//記錄每一次走法	
	public static void walk(int d,int h) {
		
		//遞迴出口
		if(d+h==3) {
			System.out.println(Arrays.toString(meet));
			return;
		}
		
		meet[d+h]='d';
		walk(d+1, h);//遇見店
		meet[d+h]='h';
		walk(d, h+1);//遇見花
	}
	
	public static void main(String[] args) {
	 
		int d =0;//遇到店的次數
		int h =0;//遇到花的次數
		walk(d, h);
	}
/*[d, d, d]
[d, d, h]
[d, h, d]
[d, h, h]
[h, d, d]
[h, d, h]
[h, h, d]
[h, h, h]*/
}

而此題除了考慮遇到店和花外,還有(1)酒的變化,不論遇到店和花,酒的量是都發生變化的(2)遇到店和花的次數有要求,一共遇到店5次,遇到花10次,已知最後一次遇到的是花,他正好把酒喝光了。

package 藍橋2014C組;

/*酒壺中有酒2鬥,逢店加一倍,遇花喝一斗。一共遇到店5次,遇到花10次,已知最後一次遇到的是花,他正好把酒喝光了。 
 請你計算李白遇到店和花的次序,可以把遇店記為a,遇花記為b*/
/*fenxi:
 *  1. 只有遇到店的次數小於5次,才可能繼續遇到店;遇到花的次數小於10次,才可能繼續遇到花;
 *  2. 最後一次遇到的是花: 那就是遇到店5次,遇到花9次時,正好此時酒還剩1鬥,這時只能遇到花,他正好把酒喝光了
 * */
public class T6 {

	static int count = 0;

	public static void walk(int wine, int d, int h) {

		// 遞迴出口
		if (d == 5 && h == 9&& wine==1) {
			count++;
			return;
		}
		if (d < 5) {
			walk(wine * 2, d + 1, h);// 遇見店,酒逢店加一倍,酒的量x2
		}
		if (h < 10) {
			walk(wine - 1, d, h + 1);// 遇花喝一斗。
		}
	}

	public static void main(String[] args) {

		int d = 0;// 遇到店的次數
		int h = 0;// 遇到花的次數
		int wine = 2;// 初始有有酒2鬥
		walk(wine, d, h);
		System.out.println(count);
	}
//14
}

7.奇怪的分式:

上小學的時候,小明經常自己發明新演算法。一次,老師出的題目是:

1/4 乘以 8/5 
小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (參見圖1.png)
老師剛想批評他,轉念一想,這個答案湊巧也對啊,真是見鬼!
對於分子、分母都是 1~9 中的一位數的情況,還有哪些算式可以這樣計算呢?
請寫出所有不同算式的個數(包括題中舉例的)。
顯然,交換分子分母后,例如:4/1 乘以 5/8 是滿足要求的,這算做不同的算式。
但對於分子分母相同的情況,2/2 乘以 3/3 這樣的型別太多了,不在計數之列!
注意:答案是個整數(考慮對稱性,肯定是偶數)。請通過瀏覽器提交。不要書寫多餘的內容。
package 藍橋2014C組;

/*對於分子、分母都是 1~9 中的一位數的情況;把分子拼接在一起,分母拼接在一起
 *但對於分子分母相同的情況, 不在計數之列;請寫出所有不同算式的個數,肯定是偶數
 *fenxi:
 *1. 與之前全排列的多重迴圈不同的是:
 *    不是這四個數字都不相同哦!!只是每一個分式的分子和分母不相同即可
 *2. ax/ay x bx/by
 *  (ax*bx)/(ay*by) 與  (ax*10+bx)/(ay*10+by)是否相等
 *   若直接看兩邊是否== ,不行,因為若有除不進的,會有誤差
 *3. 要求每一個分式的最大公約數:然後對於約分後的兩個分式,比較分子與分子  分母與分母*/
public class T7 {
	static int count = 0;

	public static void main(String[] args) {
		// ax ay第一個分式的分子和分母 bx by第二個分式的分子和分母
		for (int ax = 1; ax <= 9; ax++) {

			for (int ay = 1; ay <= 9; ay++) {
				if (ax == ay)
					continue;
				for (int bx = 1; bx <= 9; bx++) {

					for (int by = 1; by <= 9; by++) {
						if (bx == by)
							continue;
						// 求兩個分式的最大公約數
						int g1 = gcd(ax * bx, ay * by);
						int g2 = gcd(ax * 10 + bx, ay * 10 + by);
						// 對於約分後的兩個分式,比較分子與分子 分母與分母
						if ((ax * bx) / g1 == (ax * 10 + bx) / g2 && (ay * by) / g1 == (ay * 10 + by) / g2) {
							count++;
						}

					}
				}
			}
		}
		System.out.println(count);
	}

	// 求一個分式的最大公約數
	public static int gcd(int x, int y) {
		if (y == 0)
			return x;
		else
			return gcd(y, x % y);
	}
//14
}

補充:

判斷兩個分式相等,除了第一種方法:將兩個分式分別求最大公約數,進行各自的約分,然後比對它們的分子,分母都對應相等外;

第二種方法:第一個分式的分子乘以第二個分式的分母所的結果 與 第二個分式的分子乘以第一個分式的分母所的結果 比較,相等,就代表兩個分式相等;

8.蘭頓螞蟻

 平面上的正方形格子被填上黑色或白色。在其中一格正方形內有一隻“螞蟻”。
    螞蟻的頭部朝向為:上下左右其中一方。
螞蟻的移動規則十分簡單:
若螞蟻在黑格,右轉90度,將該格改為白格,並向前移一格;
若螞蟻在白格,左轉90度,將該格改為黑格,並向前移一格。

規則雖然簡單,螞蟻的行為卻十分複雜。剛剛開始時留下的路線都會有接近對稱,像是會重複,但不論起始狀態如何,螞蟻經過漫長的混亂活動後,會開闢出一條規則的“高速公路”。

螞蟻的路線是很難事先預測的。
你的任務是根據初始狀態,用計算機模擬蘭頓螞蟻在第n步行走後所處的位置。
【資料格式】

輸入資料的第一行是 m n 兩個整數(3 < m, n < 100),表示正方形格子的行數和列數。
接下來是 m 行資料。
每行資料為 n 個被空格分開的數字。0 表示白格,1 表示黑格。

接下來是一行資料:x y s k, 其中x y為整數,表示螞蟻所在行號和列號(行號從上到下增長,列號從左到右增長,都是從0開始編號)。s 是一個大寫字母,表示螞蟻頭的朝向,我們約定:上下左右分別用:UDLR表示。k 表示螞蟻走的步數。

輸出資料為兩個空格分開的整數 p q, 分別表示螞蟻在k步後,所處格子的行號和列號。

例如, 輸入:
5 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
2 3 L 5
程式應該輸出:
1 3

程式碼實現:

package 藍橋2014C組;
import java.util.Scanner;
public class T8 {

	static int row;
	static int col;
	static int[][] arr;
	static char dir;

	public static void main(String[] args) {

		Scanner scanner = new Scanner(System.in);
		int m = scanner.nextInt();// 方格的行數
		int n = scanner.nextInt();// 方格的列數
		arr = new int[m][n];// 定義二維陣列儲存方格
		// 初始化方格
		for (int i = 0; i < arr.length; i++) {
			for (int j = 0; j < arr[i].length; j++) {
				arr[i][j] = scanner.nextInt();// 輸入時,0 表示白格,1 表示黑格
			}
		}
		// 螞蟻所在行號和列號,都是從0開始編號
		row = scanner.nextInt();
		col = scanner.nextInt();
		// 螞蟻頭的朝向,我們約定:上下左右分別用:UDLR表示
		dir = scanner.next().charAt(0);// 注意scanner.next()得到是String
		// 表示螞蟻走的步數
		int k = scanner.nextInt();

		// 按照螞蟻走的步數,進行迴圈,每走一步,都按照"規則"進行,將一步規則寫進方法中
		for (int i = 1; i <= k; i++) {
			// 先轉向,再移動
			move();
		}

		System.out.println(row + " " + col);
	}

//	每走一步,都按照"規則"進行;
	// (1)必須知道螞蟻的位置(行號,列號) arr[row][col],二維陣列也需要 則這三個要改成全域性靜態變數
	// (2)獲取當前格子的顏色:利用arr[row][col]是0或1,而知道
//	  若在黑格子裡:若開始向上,則向右轉;若開始向右,則向下轉;
	public static void move() {
		if (arr[row][col] == 1) {// 若螞蟻在黑格,右轉90度,將該格改為白格,並向前移一格;
			if (dir == 'U') {
				dir = 'R';
			} else if (dir == 'R') {
				dir = 'D';
			} else if (dir == 'D') {
				dir = 'L';
			} else {
				dir = 'U';
			}
			arr[row][col] = 0;
		} else if (arr[row][col] == 0) {// 若螞蟻在白格,左轉90度,將該格改為黑格,並向前移一格。
			if (dir == 'U') {
				dir = 'L';
			} else if (dir == 'L') {
				dir = 'D';
			} else if (dir == 'D') {
				dir = 'R';
			} else {
				dir = 'U';
			}
			arr[row][col] = 1;
		}

		//// 先轉向,再移動!!!!
		if (dir == 'U') {
			row--;
		} else if (dir == 'R') {
			col++;
		} else if (dir == 'D') {
			row++;
		} else {
			col--;
		}
	}
}

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

程式碼:

package 藍橋2014C組;

import java.util.Scanner;

/*分析:
 * 1.走到某個格子時:
 * 若此寶貝的價值大:有4種選擇:向右走拿寶貝,向右走不拿寶貝,向下走拿寶貝,向下走不拿寶貝
 * 若此寶貝的價值小: 則不能那寶貝:向右走不拿寶貝,向下走不拿寶貝;
 * 2. 先判斷寶貝的價值,大,則就寫四個遞迴;小,則就寫2個遞迴;*/
public class T9 {
	static int[][] digong;
	static int n;
	static int m;
	static int k;
	static long mount;// 方案的數量

	public static void main(String[] args) {

		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();// n 行
		m = scanner.nextInt();// m列
		k = scanner.nextInt();// 要取寶貝件數
		digong = new int[m][n];// 地宮矩陣
		// 初始化地宮格中寶貝的價值
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				digong[i][j] = scanner.nextInt();
			}
		}
		move(0, 0, -1, 0);// 注意此處的預設初始寶貝最大值,因為寶貝價值可以取到0; 開始時,若第一個寶貝價值就是0; 當max==0 ,則就不拿了;而實際上是可以拿的
		System.out.println(mount);
	}

	// 取寶貝的過程實現:
	// (1)小明的位置; (2)寶貝的最大值(判斷當前寶貝的價值與手中所有寶貝進行比較,所以需要知道寶貝的最大值,是動態變化的)
	// (3) 小明手中寶貝的數量是動態變化的
	/**
	 * @param row   行走時的行
	 * @param col   行走時的列
	 * @param max   行走時的目前寶貝的最大價值
	 * @param count 行走時的寶貝的數量
	 */
	public static void move(int row, int col, int max, int count) {

		// 遞迴出口1:走出地宮外 或者 寶貝數量大於k
		if (row >= n || col >= m || count > k) {
			return;
		}
		// 遞迴出口2:
		// 不可以簡單的認為只要k==count 因為小明若走到地宮的某處還未到出口時,就已經拿夠了寶貝,就算接下來不拿,那可能也有多種方案走到出口
		// (1)當走到出口時,k==count
		// (2)當走到最後一個格子時,count=k-1,此時最後一個格子的價值又比較大,也符合條件

		if (row == n - 1 && col == m - 1) {// 走到最後一個格子
			if (count == k || (count == k - 1 && digong[row][col] > max)) {
				mount++;
				mount = mount % 1000000007;
			}
		}
		// 如果當前寶貝的價值大於目前寶貝的最大價值,有四種選擇:
		if (digong[row][col] > max) {
			move(row, col + 1, digong[row][col], count + 1);// 拿了寶貝並向右走
			move(row, col + 1, max, count);// 右不拿
			move(row + 1, col, digong[row][col], count + 1);// 下拿
			move(row + 1, col, max, count);// 下不拿
		} else {// 如果當前寶貝的價值小於目前寶貝的最大價值,有2種選擇:
			move(row, col + 1, max, count);// 右不拿
			move(row + 1, col, max, count);// 下不拿
		}
	}
}