2013第四屆藍橋杯省賽java B組題解

各題分值:

1.世紀末的星期(結果填空) 3分
2.馬虎的算式(結果填空) 6分
3.振興中華 ( 結果填空) 8分
4.黃金連分數( 結果填空) 13分
5.有理數類( 代碼填空) 5分
6.三部排序 (代碼填空) 8分
7.錯誤票據( 編程大題) 5分
8.幸運數(編程大題) 10分
9.帶分數(編程大題) 15分
10.連號區間數(編程大題) 27分

第一題

題目:世紀末的星期

曾有邪教稱19991231日是世界末日。當然該謠言已經不攻自破。
還有人稱今後的某個世紀末的1231日,如果是星期一則會...
有趣的是,任何一個世紀末的年份的1231日都不可能是星期一!! 
於是,“謠言製造商”又修改爲星期日......

1999年的1231日是星期五,請問:未來哪一個離我們最近的一個世紀末年(即xx99年)的
1231日正好是星期天(即星期日)?

請回答該年份(只寫這個4位整數,不要寫1231等多餘信息)

思路:%7後差兩天就是星期日,加5 %70或者%72都行

public class Main {  
	 public static void main(String[] args)  
	    {  
	        int year = 2000;  
	        int total = 0;  
	        for( ; ; year++)  {  
	            if(year%400==0 || (year%4==0 && year%100!=0)){  //閏年
	                total += 366;  
	            }else  {  
	                total += 365;  
	            }  
	            if((total+5)%7 == 0 && (year+"").endsWith("99")){   //判斷year是否以99結尾,
	                System.out.println(year);  
	                break;  
	            }  
	        }  
	    }  
}  

第二題

題目:馬虎的算式

小明是一個急性子,上小學的時候經常把老師寫在黑板上的題目抄錯。 
有一次,老師出得題目是:36*495=? 他卻給抄成了:396*45=? 
但結果卻很戲劇性,他的答案竟然是對的!! 
因爲36*495=396*45=17820 
類似這樣的巧合情況可能還有很多, 
比如:27*594=297*54 
假設a b c d e代表1-9不同的5個數字(注意是各不相同的數字,且不含0) 
能滿足形如:ab*cde=adb*ce這樣的算式一共有多少種呢?

1.直接枚舉暴力

public class Main {
 
	static int ans = 0;
 
	public static void main(String[] args) {
		int cnt = 0;
		for (int a = 1; a < 10; a++) {
			for (int b = 1; b < 10; b++) {
				if (b != a) {
					for (int c = 1; c < 10; c++) {
						if (c != b && c != a) {
							for (int d = 1; d < 10; d++) {
								if (d != c && d != b && d != a) {
									for (int e = 1; e < 10; e++) {
										if (e != d && e != c && e != b && e != a) {
											int t1 = a * 10 + b;
											int t2 = c * 100 + d * 10 + e;
											int t3 = a * 100 + d * 10 + b;
											int t4 = c * 10 + e;
											if (t1 * t2 == t3 * t4)
												cnt++;
										}
									}
								}
							}
						}
					}
				}
			}
		}
		System.out.println(cnt);
	}
}

2.dfs搜索

public class Main {
 
	static int ans = 0;
	static boolean[] vis = new boolean[10];
	static int[] num = new int[6];
 
	static void dfs(int pos) {
		if (pos == 6) {
			int t1 = num[1] * 10 + num[2];
			int t2 = num[3] * 100 + num[4] * 10 + num[5];
			int t3 = num[1] * 100 + num[4] * 10 + num[2];
			int t4 = num[3] * 10 + num[5];
			if (t1 * t2 == t3 * t4)
				ans++;
			return;
		}
		for (int i = 1; i < 10; i++) {
			if (!vis[i]) {
				vis[i] = true;
				num[pos] = i;
				dfs(pos + 1);
				vis[i] = false;
			}
		}
	}
 
	public static void main(String[] args) {
		dfs(1);
		System.out.println(ans);
	}
}
答案:142

第三題

題目:振興中華

 小明參加了學校的趣味運動會,其中的一個項目是:跳格子。
    地上畫着一些格子,每個格子裏寫一個字,如下所示:(也可參見p1.jpg)
   從我做起振
   我做起振興
   做起振興中
   起振興中華

在這裏插入圖片描述

比賽時,先站在左上角的寫着“從”字的格子裏,可以橫向或縱向跳到相鄰的格子裏,
但不能跳到對角的格子或其它位置。一直要跳到“華”字結束。
要求跳過的路線剛好構成“從我做起振興中華”這句話。
請你幫助小明算一算他一共有多少種可能的跳躍路線呢?

dfs

public class Main {
 
	static int ans = 0;
    static int[] x= {1,-1,0,0};
    static int[] y= {0,0,1,-1};
    static int[][] a=new int[4][5];
	static char[] s = "從我做起振興中華".toCharArray();
    static char[][] map = { "從我做起振".toCharArray(), "我做起振興".toCharArray(), "做起振興中".toCharArray(),
			"起振興中華".toCharArray() };
    
	static void dfs(int i,int j,int pos) {
          if(pos==8) {
        	  ans++;
        	  return;
          }else {
        	  for(int k=0;k<4;k++) {
        		  int x1=i+x[k];
        		  int y1=j+y[k];
        		  if(x1<4 && x1>=0 && y1<=4 && y1>=0 && map[x1][y1] == s[pos]) {
        			  dfs(x1,y1,pos+1);
        		  }
        	  }
          }
	}
 
	public static void main(String[] args) {
		dfs(0,0,1);
		System.out.println(ans);
	}
}

第四題

題目:黃金連分數

黃金分割數0.61803... 是個無理數,這個常數十分重要,在許多工程問題中會出現。
有時需要把這個數字求得很精確。
對於某些精密工程,常數的精度很重要。也許你聽說過哈勃太空望遠鏡,
它首次升空後就發現了一處人工加工錯誤,對那樣一個龐然大物,
其實只是鏡面加工時有比頭髮絲還細許多倍的一處錯誤而已,卻使它成了“近視眼”!!
言歸正傳,我們如何求得黃金分割數的儘可能精確的值呢?有許多方法。
比較簡單的一種是用連分數:

                                1
    黃金數 = ---------------------
                                 1
                  1 + -----------------
                                   1
                        1 + -------------
                                        1
                               1 + ---------
                                       1 + ...

這個連分數計算的“層數”越多,它的值越接近黃金分割數。
請你利用這一特性,求出黃金分割數的足夠精確值,要求四捨五入到小數點後100位。
小數點後3位的值爲:0.618
小數點後4位的值爲:0.6180
小數點後5位的值爲:0.61803
小數點後7位的值爲:0.6180340
(注意尾部的0,不能忽略)
你的任務是:寫出精確到小數點後100位精度的黃金分割值。
注意:尾數的四捨五入! 尾數是0也要保留!
顯然答案是一個小數,其小數點後有100位數字,請通過瀏覽器直接提交該數字。
注意:不要提交解答過程,或其它輔助說明類的內容。

解釋:大佬鏈接 https://blog.csdn.net/allyyhh/article/details/88423797

import java.math.BigDecimal;
import java.math.BigInteger;

public class Main {

    	public static void main(String[] args) {
    		BigInteger a = BigInteger.ONE;//1
    		BigInteger b = BigInteger.ONE;//1
    		//斐波那契數列的迭代形式
    		for (int i = 3; i < 300; i++) {
    			BigInteger tmp = b;
    			b = a.add(b);
    			a = tmp;
    		}
    		//大浮點數的除法
    		BigDecimal divide = new BigDecimal(a,110).divide(new BigDecimal(b,110),101, BigDecimal.ROUND_HALF_DOWN);
    	    System.out.println(divide);
    	 }
    }
答案:0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911375

第五題

題目:有理數類
有理數就是可以表示爲兩個整數的比值的數字。一般情況下,我們用近似的小數表示。但有些時候,不允許出現誤差,必須用兩個整數來表示一個有理數。
這時,我們可以建立一個“有理數類”,下面的代碼初步實現了這個目標。爲了簡明,它只提供了加法和乘法運算。

class Rational
{
private long ra;
private long rb;

private long gcd(long a, long b){
if(b==0) return a;
return gcd(b,a%b);
}
public Rational(long a, long b){
ra = a;
rb = b; 
long k = gcd(ra,rb);
if(k>1){ //需要約分
ra /= k;  
rb /= k;
}
}
// 加法
public Rational add(Rational x){
return ________________________________________;  //填空位置
}
// 乘法
public Rational mul(Rational x){
return new Rational(ra*x.ra, rb*x.rb);
}
public String toString(){
if(rb==1) return "" + ra;
return ra + "/" + rb;
}
}
使用該類的示例:
Rational a = new Rational(1,3);
Rational b = new Rational(1,6);
Rational c = a.add(b);
System.out.println(a + "+" + b + "=" + c);
請分析代碼邏輯,並推測劃線處的代碼,通過網頁提交
注意:僅把缺少的代碼作爲答案,千萬不要填寫多餘的代碼、符號或說明文字!!
答案:return new Rational(x.rb * ra + x.ra * rb,rb * x.rb)

第六題

題目:三部排序

一般的排序有許多經典算法,如快速排序、希爾排序等。

    但實際應用時,經常會或多或少有一些特殊的要求。我們沒必要套用那些經典算法,
    可以根據實際情況建立更好的解法。

    比如,對一個整型數組中的數字進行分類排序:

    使得負數都靠左端,正數都靠右端,0在中部。注意問題的特點是:
    負數區域和正數區域內並不要求有序。可以利用這個特點通過1次線性掃描就結束戰鬥!!

    以下的程序實現了該目標。

    其中x指向待排序的整型數組,len是數組的長度。

void sort3p(int* x, int len)

{

       int p = 0;

       int left = 0;

       int right = len-1;

      

       while(p<=right){

              if(x[p]<0){

                     int t = x[left];

                     x[left] = x[p];

                     x[p] = t;

                     left++;

                     p++;

              }

              else if(x[p]>0){

                     int t = x[right];

                     x[right] = x[p];

                     x[p] = t;

                     right--;                 

              }

              else{

                     __________________________;  //填空位置

              }

       }      

}

   如果給定數組:

   25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0

   則排序後爲:

   -3,-2,-16,-5,0,0,0,21,19,33,25,16,18,25

請分析代碼邏輯,並推測劃線處的代碼,通過網頁提交

注意:僅把缺少的代碼作爲答案,千萬不要填寫多餘的代碼、符號或說明文字!! 
答案:p++;

第七題

題目:錯誤票據

某涉密單位下發了某種票據,並要在年終全部收回。

每張票據有唯一的ID號。全年所有票據的ID號是連續的,但ID的開始數碼是隨機選定的。

因爲工作人員疏忽,在錄入ID號的時候發生了一處錯誤,造成了某個ID斷號,
另外一個ID重號。

你的任務是通過編程,找出斷號的ID和重號的ID。

假設斷號不可能發生在最大和最小號。

要求程序首先輸入一個整數N(N<100)表示後面數據行數。

接着讀入N行數據。

每行數據長度不等,是用空格分開的若干個(不大於100個)正整數(不大於100000)

每個整數代表一個ID號。

要求程序輸出1行,含兩個整數m n,用空格分隔。

其中,m表示斷號ID,n表示重號ID

例如:

用戶輸入:

2

5 6 8 11 9

10 12 9

則程序輸出:

7 9

再例如:

用戶輸入:

6

164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196

172 189 127 107 112 192 103 131 133 169 158

128 102 110 148 139 157 140 195 197

185 152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190

149 138 142 146 199 126 165 156 153 193 144 166 170 121 171 132 101 194 187 188

113 130 176 154 177 120 117 150 114 183 186 181 100 163 160 167 147 198 111 119

則程序輸出:

105 120

思路:先用一個數組排序,再用另一個數組標記
注意:複製樣例時把空行刪掉!!!

import java.util.Arrays;
import java.util.Scanner;

public class Main { 
    	public static void main(String[] args) {
    		Scanner in=new Scanner(System.in);
    		int[] x=new int[100001];
    		int[] y=new int[100001];
    		int k=0;
        	String[] s= {};
        	String str="";
    		int n=in.nextInt();
    		in.nextLine();
    		
            for(int i=0;i<n;i++) {
            	str=in.nextLine();
            	s=str.split(" ");
            	for(int j=0;j<s.length;j++) {
            		x[k]=Integer.parseInt(s[j]);
            		k++;
            	}
            }
            Arrays.sort(x,0,k);
            
            for(int i=0;i<k;i++) {
            	y[x[i]]+=1;
            }
            for(int i=x[0];i<=x[k-1];i++) {
            	if(y[i]==0) System.out.print(i+" ");
            	if(y[i]==2) System.out.print(i+" ");
            }
    	 }
    }

第八題

題目:幸運數

幸運數是波蘭數學家烏拉姆命名的。它採用與生成素數類似的“篩法”生成。 
首先從1開始寫出自然數1,2,3,4,5,6,....
1 就是第一個幸運數。
我們從2這個數開始。把所有序號能被2整除的項刪除,變爲:
1 _ 3 _ 5 _ 7 _ 9 ....
把它們縮緊,重新記序,爲:
1 3 5 7 9 .... 。這時,3爲第2個幸運數,然後把所有能被3整除的序號位置的數刪去。注意,是序號位置,不是那個數本身能否被3整除!! 刪除的應該是511, 17, ...
此時7爲第3個幸運數,然後再刪去序號位置能被7整除的(19,39,...)
最後剩下的序列類似:
1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, ...

Input

輸入兩個正整數m n, 用空格分開 (m < n < 200*200)

Output

程序輸出 位於m和n之間的幸運數的個數(不包含m和n)

Sample Input

1 20

Sample Output

5
import java.util.Scanner;

public class Main { 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
 
		Scanner sc = new Scanner(System.in);
		int m = sc.nextInt();
		int n = sc.nextInt();
		int[] a = new int[n];
		for (int i = 0; i < n ; i++) {
			a[i] = 2 * i + 1;
		}
		int l = 1;
		int p = l + 1;
		while (true) {
			p = l + 1;
			for (int j = l + 1; j < n; j++) {
				if ((j + 1) % a[l] == 0)
					continue;
				else {
					a[p++] = a[j];
				}
			}
			l++;
			if (a[l] > n)
				break;
		}
 
		int ans=0;
		for (int i = 0; i < a.length; i++) {
			if (a[i] >= n)
				break;
			if(a[i]>m) {
				ans++;
			}
 
		}
		System.out.println(ans);
	}
 
}

第九題

題目:帶分數

100 可以表示爲帶分數的形式:100 = 3 + 69258 / 714。

還可以表示爲:100 = 82 + 3546 / 197。

注意特徵:帶分數中,數字1~9分別出現且只出現一次(不包含0)。

類似這樣的帶分數,10011 種表示法。

輸入格式
從標準輸入讀入一個正整數N (N<1000*1000)

輸出格式
程序輸出該數字用數碼1~9不重複不遺漏地組成帶分數表示的全部種數。

注意:不要求輸出每個表示,只統計有多少表示法!

樣例輸入1
100
樣例輸出1
11
樣例輸入2
105
樣例輸出2
6

第十題

題目:連號區間數

小明這些天一直在思考這樣一個奇怪而有趣的問題:
在1~N的某個全排列中有多少個連號區間呢?這裏所說的連號區間的定義是:
如果區間[L, R] 裏的所有元素(即此排列的第L個到第R個元素)遞增排序後能得到一個長度爲R-L+1的“連續”數列,則稱這個區間連號區間。
當N很小的時候,小明可以很快地算出答案,但是當N變大的時候,問題就不是那麼簡單了,現在小明需要你的幫助。
輸入格式:
第一行是一個正整數N (1 <= N <= 50000), 表示全排列的規模。
第二行是N個不同的數字Pi(1 <= Pi <= N), 表示這N個數字的某一全排列。
輸出格式:
輸出一個整數,表示不同連號區間的數目。

示例:
用戶輸入:
4
3 2 4 1
程序應輸出:
7
用戶輸入:
5
3 4 2 5 1
程序應輸出:
9

解釋:
第一個用例中,有7個連號區間分別是:[1,1], [1,2], [1,3], [1,4], [2,2], [3,3], [4,4]
第二個用例中,有9個連號區間分別是:[1,1], [1,2], [1,3], [1,4], [1,5], [2,2], [3,3], [4,4], [5,5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章