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

一葉之修發表於2019-02-28

 藍橋杯歷年真題題目及題解目錄彙總 

 

  1. 結果填空 (滿分2分)
  2. 結果填空 (滿分4分)
  3. 結果填空 (滿分7分)
  4. 程式碼填空 (滿分4分)
  5. 程式碼填空 (滿分7分)
  6. 結果填空 (滿分10分)
  7. 結果填空 (滿分13分)
  8. 程式設計(滿分10分)
  9. 程式設計(滿分18分)
  10. 程式設計(滿分25分)

 

 


1.標題:猜年齡

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

    請你寫出:小明的較小的妹妹的年齡。


注意: 只寫一個人的年齡數字,請通過瀏覽器提交答案。不要書寫任何多餘的內容。

 答案:10  2個for

public class _01猜年齡1 {

	public static void main(String[] args) {

		for(int i=1;i<=100;i++)
			for(int j=i;j<=i+8;j++)
				if(i*j==6*(i+j))
					System.out.println(i+" "+j);

	}

}

 

 


2.標題:等額本金

    小明從銀行貸款3萬元。約定分24個月,以等額本金方式還款。

    這種還款方式就是把貸款額度等分到24個月。每個月除了要還固定的本金外,還要還貸款餘額在一個月中產生的利息。

    假設月利率是:0.005,即:千分之五。那麼,

    第一個月,小明要還本金 1250, 還要還利息:30000 * 0.005,總計 1400
    第二個月,本金仍然要還 1250, 但利息為:(30000-1250) * 0.005 總計 1393.75

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

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

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

public class C組_等額本金 {

	public static void main(String[] args) {
		int sum=30000;
		int x = 1500;
		for(int i=1;i<=15;i++) {
			System.out.println(1250+sum*0.005+"   "+i);
			sum-=1250;
		}
			
		System.out.println();
	}

}


3.標題:猜字母

    把abcd...s共19個字母組成的序列重複拼接106次,得到長度為2014的串。

    接下來刪除第1個字母(即開頭的字母a),以及第3個,第5個等所有奇數位置的字母。

    得到的新串再進行刪除奇數位置字母的動作。如此下去,最後只剩下一個字母,請寫出該字母。

答案是一個小寫字母,請通過瀏覽器提交答案。不要填寫任何多餘的內容。

/*
題目:猜字母
      把abcd...s共19個字母組成的序列重複拼接106次,得到長度為2014的串。
      接下來刪除第1個字母(即開頭的字母a),以及第3個,第5個等所有奇數位置的字母。
      得到的新串再進行刪除奇數位置字母的動作。如此下去,最後只剩下一個字母,請寫出該字母。
答案:q 
*/
    
#include <iostream>
using namespace std;
 
int main(){
	string s="abcdefghijklmnopqrs";
	string ss;
	for(int i=0;i<106;i++){
		ss+=s;		//拼接106次 
	}
	while(ss.size()>1){		//判斷迴圈結束 
		for(int i=0;i<ss.size();i++){
			ss.replace(i,1,"");		//replace()函式 的使用 
		}
	}
 
	cout<<ss;
	return 0;
}
 
/*
知識點 
	replace()函式: 
	
	用str中的num個字元替換本字串中的字元,從index開始 
	用str中的num2個字元(從index2開始)替換本字串中的字元,從index1開始,最多num1個字元 
	用str中的num個字元(從index開始)替換本字串中的字元 
	用str中的num2個字元(從index2開始)替換本字串中的字元,從index1開始,num1個字元 
	用num2個ch字元替換本字串中的字元,從index開始 
	用str中的字元替換本字串中的字元,迭代器start和end指示範圍 
	用str中的num個字元替換本字串中的內容,迭代器start和end指示範圍, 
	用num個ch字元替換本字串中的內容,迭代器start和end指示範圍. 
	
	例如,以下程式碼顯示字串"They say he carved it himself...find your soul-mate, Homer." 
	    string s = "They say he carved it himself...from a BIGGER spoon";
	    string s2 = "find your soul-mate, Homer.";
	
	    s.replace( 32, s2.length(), s2 );
	
	    cout << s << endl;
	
*/


4.標題:大衍數列

    中國古代文獻中,曾記載過“大衍數列”, 主要用於解釋中國傳統文化中的太極衍生原理。

    它的前幾項是:0、2、4、8、12、18、24、32、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%2==0

 


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);
    }
}

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

注意:不要填寫題面已有的內容,也不要填寫任何說明、解釋文字。

1 + n%3  ,求模操作,可以把n=1,2,3代進去驗證

   


6.標題:李白打酒

    話說大詩人李白,一生好飲。幸好他從不開車。

    一天,他提著酒壺,從家裡出來,酒壺中有酒2鬥。他邊走邊唱:

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

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

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

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

14,讀完題目知道要考遞迴了,理清思路,5(a)次店必須都去,10(b)次花都要遇見,而且結束的時候酒要喝完,最穩的寫法就是寫3個遞迴出口,不過發現可以剪枝,3個是不必要的,當一個變數為0就可以進行最後的判斷了,嚴謹的話還要給酒壺是否為空一個判斷,不過這裡now為負的話,喝酒也不會為正,不可能為答案

public class _02李白打酒1 {

	public static void main(String[] args) {
		System.out.println(f(5,10,2));
	}
	
	static int f(int a,int b,int now) {
		if(b==0)
			return (a==0&&now==0)?1:0;
		if(a==0)
			return (b==now)?1:0;
		
		return f(a-1,b,2*now) + f(a,b-1,now-1);
	}

}

 

 


7.標題:奇怪的分式

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

    1/4 乘以 8/5 

    小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (參見圖1.png)

    老師剛想批評他,轉念一想,這個答案湊巧也對啊,真是見鬼!

    對於分子、分母都是 1~9 中的一位數的情況,還有哪些算式可以這樣計算呢?

    請寫出所有不同算式的個數(包括題中舉例的)。

    顯然,交換分子分母后,例如:4/1 乘以 5/8 是滿足要求的,這算做不同的算式。

    但對於分子分母相同的情況,2/2 乘以 3/3 這樣的型別太多了,不在計數之列!

注意:答案是個整數(考慮對稱性,肯定是偶數)。請通過瀏覽器提交。不要書寫多餘的內容。


   

14,暴力4個for 列印驗證 

public class _06奇怪的分式 {
 
	public static void main(String[] args) {
		// A/B x C/D = E/F   A*C*F = E*B*D
		int ans=0;
		for(int a=1;a<10;a++)
			for(int b=1;b<10;b++)
				for(int c=1;c<10;c++)
					for(int d=1;d<10;d++) {
						int e = 10*a+c;
						int f = 10*b+d;
						if(a==b || c==d)
							continue;
 
						if(a*c*f==e*b*d) {
							ans++;
							System.out.println(a+"/"+b+" x "+c+"/"+d+" = "+e+"/"+f+"  "+ans);
						}
						
					}
		
	}
 
}


8.標題:蘭頓螞蟻

    蘭頓螞蟻,是於1986年,由克里斯·蘭頓提出來的,屬於細胞自動機的一種。

    平面上的正方形格子被填上黑色或白色。在其中一格正方形內有一隻“螞蟻”。
    螞蟻的頭部朝向為:上下左右其中一方。

    螞蟻的移動規則十分簡單:
    若螞蟻在黑格,右轉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

再例如, 輸入:
3 3
0 0 0
1 1 1
1 1 1
1 1 U 6
程式應該輸出:
0 0


資源約定:
峰值記憶體消耗(含虛擬機器) < 256M
CPU消耗  < 1000ms


請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。

所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意:不要使用package語句。不要使用jdk1.7及以上版本的特性。
注意:主類的名字必須是:Main,否則按無效程式碼處理。

前段時間寫過:[藍橋杯][2014年第五屆真題]蘭頓螞蟻

和普通的搜尋差不多,寫dx,dy函式的時候要按順時針方向了,因為它向左向右,實際上就是順時針和逆時針,陣列有沒越界都不用管了,題目根本沒提,預設沒越界,還見識過 一個 for 4個 if 的暴力做法,很prefer

import java.util.Scanner;
 
public class 蘭頓螞蟻 {
 
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		m = in.nextInt();
		mp = new int[n][m];
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
				mp[i][j] = in.nextInt();
		int x=0,y=0,s=0,k=0;
 
		x = in.nextInt();
		y = in.nextInt();
		String str = in.next();//UDLR
		k = in.nextInt();
		if(str.equals("U"))
			s=0;
		else if(str.equals("R"))
			s=1;
		else if(str.equals("D"))
			s=2;
		else if(str.equals("L"))
			s=3;
		
		dfs(x,y,s,k);
	}
	
	static int n,m;
	static int[] dx = new int[] {-1,0,1,0};
	static int[] dy = new int[] {0,1,0,-1};
	static int[][] mp;
	
	static void dfs(int x,int y,int s,int k) {
		if(k==0) {
			System.out.println(x+" "+y);
			return;
		}
//		System.out.println(":"+x+" "+y);
		if(mp[x][y]==1) {
			mp[x][y] = 0;
			dfs(x+dx[(s+1+4)%4],y+dy[(s+1+4)%4],(s+1+4)%4,k-1);
		}else if(mp[x][y]==0) {
			mp[x][y] = 1;
			dfs(x+dx[(s-1+4)%4],y+dy[(s-1+4)%4],(s-1+4)%4,k-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


請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。

所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意:不要使用package語句。不要使用jdk1.7及以上版本的特性。
注意:主類的名字必須是:Main,否則按無效程式碼處理。

問題 1436: [藍橋杯][2014年第五屆真題]地宮取寶 

之前寫過,不過隔的久,風格有點差別,記憶化搜尋,這裡是從出口到入口的遞迴,那個部落格是入口開始的,初始化為-1的話,判斷完後記得設為0,不然你的答案莫名的-1-1-1,用四維陣列記憶

import java.util.Scanner;
 
public class _09地宮取寶1 {
 
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		m = in.nextInt();
		k = in.nextInt();
		a = new int[n+5][m+5];
		int max=0;
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++) {
				a[i][j] = in.nextInt();
				max = Math.max(max, a[i][j]);
			}
		memo = new int[n+5][m+5][k+5][max+5];
		for(int i=0;i<=n;i++)
			for(int j=0;j<=m;j++)
				for(int x=0;x<=k;x++)
					for(int y=0;y<=max+1;y++)
						memo[i][j][x][y] = -1;
 
		System.out.println(f(n-1,m-1,k,max+1));
 
	}
	
	static int n,m,k;
	static int[][][][] memo;
	static int[][] a;
	
	static int f(int x,int y,int now,int max) {
		if(memo[x][y][now][max]!=-1)
			return memo[x][y][now][max];
		
		if(x==0 && y==0) {
			if(now==0)
				return 1;
			if(now==1 && max>a[x][y])
				return 1;
			return 0;
		}
 
		memo[x][y][now][max] = 0;
		
		if(now>0) {
			if(x>0) {
				memo[x][y][now][max] = (memo[x][y][now][max]+f(x-1,y,now,max))%1000000007;
				if(max>a[x][y])
					memo[x][y][now][max] = (memo[x][y][now][max]+f(x-1,y,now-1,a[x][y]))%1000000007;
			}
			if(y>0) {
				memo[x][y][now][max] = (memo[x][y][now][max]+f(x,y-1,now,max))%1000000007;
				if(max>a[x][y])
					memo[x][y][now][max] = (memo[x][y][now][max]+f(x,y-1,now-1,a[x][y]))%1000000007;
			}
		} else {
			if(x>0) 
				memo[x][y][now][max] = (memo[x][y][now][max]+f(x-1,y,now,max))%1000000007;
			if(y>0) 
				memo[x][y][now][max] = (memo[x][y][now][max]+f(x,y-1,now,max))%1000000007;
		}
		return memo[x][y][now][max]%1000000007;
	}
 
}

 


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


請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。

所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意:不要使用package語句。不要使用jdk1.7及以上版本的特性。
注意:主類的名字必須是:Main,否則按無效程式碼處理。

數學題,考點太多了

  1. 第x行第y列被翻動的總次數?
  2. 考慮第1行,第y列,y有多少真因子,就會被翻動多少次,而所有的y中,只有平方數的真因子個數為奇數(約數總是成對出現的)
  3. 考慮第1列,第x行,x有多少真因子,就會被翻動多少次,而所有的x中,只有平方數的真因子個數為奇數
  4. x,y硬幣被翻動的次數=x真因子個數*y真因子個數,只有奇數*奇數=奇數,所以,若要x,y為反面,必須x,y都是平方數
  5. 因此,反面硬幣總數=m中的平方數的個數*n中平方數的個數
  6. 那麼在m中有多少個平方數呢?答案是sqrt(m)向下取整個,如9內有三個平方數1,4,9;16裡面有4個平方數1,4,9,16;25內有5個平方數
  7. 因此此題等價於求sqrt(m)*sqrt(n),那麼怎麼對一個很大的數開平方呢?
  8. 假設一個數的長度為length,其平方根的長度為length/2(偶數)或者length/2+1(奇數)
  9. 我們可以從高位不停地試探,每一個取平方後恰好不超過目標平方數的值
/*
標題:矩陣翻硬幣
    小明先把硬幣擺成了一個 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;
對於100%的資料,n、m <= 10^1000(10的1000次方)。
資源約定:
峰值記憶體消耗(含虛擬機器) < 256M
CPU消耗  < 2000ms
請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意:不要使用package語句。不要使用jdk1.7及以上版本的特性。
注意:主類的名字必須是:Main,否則按無效程式碼處理。
*/
 
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;
 
//第x行第y列被翻動的總次數?
//考慮第1行,第y列,y有多少真因子,就會被翻動多少次,而所有的y中,只有平方數的真因子個數為奇數(約數總是成對出現的)
//考慮第1列,第x行,x有多少真因子,就會被翻動多少次,而所有的x中,只有平方數的真因子個數為奇數
//x,y硬幣被翻動的次數=x真因子個數*y真因子個數,只有奇數*奇數=奇數,所以,若要x,y為反面,必須x,y都是平方數
//因此,反面硬幣總數=m中的平方數的個數*n中平方數的個數
//那麼在m中有多少個平方數呢?答案是sqrt(m)向下取整個,如9內有三個平方數1,4,9;16裡面有4個平方數1,4,9,16;25內有5個平方數
//因此此題等價於求sqrt(m)*sqrt(n),那麼怎麼對一個很大的數開平方呢?
//假設一個數的長度為length,其平方根的長度為length/2(偶數)或者length/2+1(奇數)
//我們可以從高位不停地試探,每一個取平方後恰好不超過目標平方數的值
public class _10矩陣翻硬幣 {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    String s1 = sc.next();
    String s2 = sc.next();
    System.out.println(sqrt(s1).multiply(sqrt(s2)));
  }
 
  private static BigInteger sqrt(String s) {
    int length = s.length();
    int len = 0;
    if (length % 2 == 0)
      len = length / 2;
    else
      len = length / 2 + 1;
    char[] sArr = new char[len];
    Arrays.fill(sArr, '0');
    BigInteger target = new BigInteger(s);
    for (int pos = 0; pos < len; pos++) {
      for (char c = '1'; c <= '9'; c++) {
        sArr[pos] = c;//在pos這個位置上試著填入1-9
        BigInteger pow = new BigInteger(String.valueOf(sArr)).pow(2);//平方
        if (pow.compareTo(target) == 1)//試探數的平方更大
        {
          sArr[pos] -= 1;
          break;
        }
      }
    }
    return new BigInteger(String.valueOf(sArr));
  }
}

 

相關文章