2013年藍橋杯廣東省賽真題

1、

題目標題: 高斯日記

    大數學家高斯有個好習慣:無論如何都要記日記。

    他的日記有個與衆不同的地方,他從不註明年月日,而是用一個整數代替,比如:4210

    後來人們知道,那個整數就是日期,它表示那一天是高斯出生後的第幾天。這或許也是個好習慣,它時時刻刻提醒着主人:日子又過去一天,還有多少時光可以用於浪費呢?

    高斯出生於:1777年4月30日。

    在高斯發現的一個重要定理的日記上標註着:5343,因此可算出那天是:1791年12月15日。

    高斯獲得博士學位的那天日記上標着:8113  

    請你算出高斯獲得博士學位的年月日。

提交答案的格式是:yyyy-mm-dd, 例如:1980-03-21

請嚴格按照格式,通過瀏覽器提交答案。

注意:只提交這個日期,不要寫其它附加內容,比如:說明性的文字

解題思路

關於這道題,由於僅爲填空題,我們可以用比較作弊的方式得出結果,如果願意,甚至可以用手算得出結果。因此可以判斷這道題爲水題。

那麼關於這道題得簡單做法。實現代碼如下

#include<iostream>
#include<cstdio>
using namespace std;
int Year = 1777, Month = 4, Day = 30;
int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};  //用month數組存儲各月日期 
int add(int month[])   //統計當年總日期 
{
	int sum = 0;
	for(int i = 1; i <= 12; i++)
	{
		sum+=month[i];
	}
	return sum;
}
int main()
{
	int num = 8113;      
	int temp = 31+30+31+31+30+31+30+31+2;  //作弊手法,將77年得所以天數先去掉。2表示4月30日那天加上1月1日 
	num-=temp;
	Year++;
	Month = 1;
	Day = 1;
	while(num>0)  //運用循環逐步將日期推算出來 
	{
		if((Year%4==0&&Year%100!=0)||(Year%400==0))  //判斷是否爲閏年 
		{
			month[2] = 29;
		}
		else
		{
			month[2] = 28;
		}
		if(num >= add(month))
		{
			num-=add(month);
			Year++;
		}
		else if(num >= month[Month])  
		{
			num-=month[Month];
			Month++;
		}
		else if(num >= 1)
		{
			num--;
			Day++;
		}
	}
	printf("%d-%.02d-%.02d",Year,Month,Day);//輸出結果 
	return 0;
}

標題:馬虎的算式

    小明是個急性子,上小學的時候經常把老師寫在黑板上的題目抄錯了。

    有一次,老師出的題目是:36 x 495 = ?

    他卻給抄成了:396 x 45 = ?

    但結果卻很戲劇性,他的答案竟然是對的!!

    因爲 36 * 495 = 396 * 45 = 17820

    類似這樣的巧合情況可能還有很多,比如:27 * 594 = 297 * 54

    假設 a b c d e 代表1~9不同的5個數字(注意是各不相同的數字,且不含0)

    能滿足形如: ab * cde = adb * ce 這樣的算式一共有多少種呢?

請你利用計算機的優勢尋找所有的可能,並回答不同算式的種類數。

滿足乘法交換律的算式計爲不同的種類,所以答案肯定是個偶數。

答案直接通過瀏覽器提交。

注意:只提交一個表示最終統計種類數的數字,不要提交解答過程或其它多餘的內容

 解題思路

觀察題目可以知道,只要知道這道題涉及全排列問題就基本上很容易解出了。

實現代碼如下

#include<iostream>
#include<cstdio>
using namespace std;
int num[5], book[10], sum = 0;  //用book做標記,標記在某時刻對應該位置得num數組數值是否被使用 
void target(int n)
{
	if(n==5)
	{
		
		int tmp1 = (num[0]*10+num[1])*(num[2]*100+num[3]*10+num[4]);
		int tmp2 = (num[2]*10+num[4])*(num[0]*100+num[3]*10+num[1]);
		if(tmp1==tmp2)
		{
			sum++;
		}
	}
	else
	{
		for(int i = 1; i <= 9; i++)
		{
			if(!book[i])   //若結果爲真表示該位置數值未被使用,那麼將其放在Num的需求位置上,標記值變1.重新調用函數。使用完標記爲0 
			{
				num[n] = i;
				book[i] = 1;
				target(n+1);
				book[i] = 0;
			}
		}
	}
}
int main()
{
	int n = 0;
	target(n);
	cout << sum << endl;
	return 0;
}

題目標題: 第39級臺階

    小明剛剛看完電影《第39級臺階》,離開電影院的時候,他數了數禮堂前的臺階數,恰好是39級!

    站在臺階前,他突然又想着一個問題:

    如果我每一步只能邁上1個或2個臺階。先邁左腳,然後左右交替,最後一步是邁右腳,也就是說一共要走偶數步。那麼,上完39級臺階,有多少種不同的上法呢?

    請你利用計算機的優勢,幫助小明尋找答案。

要求提交的是一個整數。

注意:不要提交解答過程,或其它的輔助說明文字。解題思路

閱讀題意後可知道本題考察的是一個遞歸的思想。重點不要忽略在上到39級臺階時是偶數步數。

實現代碼如下

#include<iostream>
#include<cstdio>
using namespace std;
int sum = 0;
void target(int n, int num)
{
	if(n > 39)
	{
		return;
	}
	else if(n == 39)
	{
		if(num%2==0)
		{
			sum++;
		}
	}
	else
	{
		target(n+1, num+1);
		target(n+2, num+1);
	}
}
int main()
{
	int n = 0;
	int num = 0;
	target(n+1,num+1);
	target(n+2,num+1);
	cout << sum << endl;
	return 0;
}

題目標題:前綴判斷

    如下的代碼判斷 needle_start指向的串是否爲haystack_start指向的串的前綴,如不是,則返回NULL。

    比如:"abcd1234" 就包含了"abc" 爲前綴

char*prefix(char* haystack_start, char* needle_start)

{

       char* haystack = haystack_start;

       char* needle = needle_start;

       while(*haystack && *needle){

              if(______________________________)return NULL;  //填空位置

       }

       if(*needle) return NULL;

       return haystack_start;

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

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

答案:*haystack++ != *needle++


標題:三部排序

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

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

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

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

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

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

voidsort3p(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 119

10 12 9

則程序輸出:

7 9

再例如:

用戶輸入:

6

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

172 189127 107 112 192 103 131 133 169 158

128 102110 148 139 157 140 195 197

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

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

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

則程序輸出:

105 120

資源約定:

峯值內存消耗 < 64M

CPU消耗  < 1000ms

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

所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。

注意:main函數需要返回0

注意:只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操作系統的特殊函數。

注意:所有依賴的函數必須明確地在源文件中 #include <xxx>, 不能通過工程設置而省略常用頭文件。

提交時,注意選擇所期望的編譯器類型

解題思路

這道題我也不知道自己是否正確,因爲在實現代碼中寫入的第一個整數值在整塊代碼中並未起到任何作用

但題目給的所有測試數據都通過,應該也可以吧

下面是實現代碼

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
	int arr[10000], note = 0;
	char str[100][1000];
	int T;
	cin >> T;
	getchar();
	for(int i = 0; i < T; i++){
		gets(str[i]);
		int node = 0, tmp = 0;
		while(true){
			if(str[i][node]==' '){
				arr[note++] = tmp;
				tmp = 0;
			}
			else if(str[i][node] == '\0'){
				arr[note++] = tmp;
				tmp = 0;
				break;
			}
			else{
				tmp = tmp*10+str[i][node]-'0';
			}
			node++;
		}
	}
	sort(arr, arr+note);
	int a = 0, b = 0;
	for(int i = 1; i < note; i++){
		if(arr[i]-arr[i-1] == 2){
			a = arr[i]-1;
		}
		if(arr[i] == arr[i-1]){
			b = arr[i];
		} 
		if(a!=0 && b!=0)break; 
	}
	cout << a << " " << b << endl; 
	return 0;
}



題目標題:翻硬幣

    小明正在玩一個“翻硬幣”的遊戲。

    桌上放着排成一排的若干硬幣。我們用 * 表示正面,用 o 表示反面(是小寫字母,不是零)。

    比如,可能情形是:**oo***oooo

    如果同時翻轉左邊的兩個硬幣,則變爲:oooo***oooo

    現在小明的問題是:如果已知了初始狀態和要達到的目標狀態,每次只能同時翻轉相鄰的兩個硬幣,那麼對特定的局面,最少要翻動多少次呢?

    我們約定:把翻動相鄰的兩個硬幣叫做一步操作,那麼要求:

程序輸入:

兩行等長的字符串,分別表示初始狀態和要達到的目標狀態。每行的長度<1000

程序輸出:

一個整數,表示最小操作步數

例如:

用戶輸入:

**********

o****o****

程序應該輸出:

5

再例如:

用戶輸入:

*o**o***o***

*o***o**o***

程序應該輸出:

1

資源約定:

峯值內存消耗 < 64M

CPU消耗  < 1000ms

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

所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。

注意:main函數需要返回0

注意:只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操作系統的特殊函數。

注意:所有依賴的函數必須明確地在源文件中 #include <xxx>, 不能通過工程設置而省略常用頭文件。

提交時,注意選擇所期望的編譯器類型。

解題思路

閱讀題意解法完全是我第一篇博客裏特殊密碼鎖的解法,有興趣可點擊我博客查看

實現代碼如下

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
	int Count = 0;
	char s[1000], S[1000];
	cin >> s >> S;
	for(int i = 1; i < strlen(s); i++){
		if(s[i-1]!=S[i-1]){
			if(s[i-1] == '*'){
				s[i-1] == 'o'; 
			}
			else{
				s[i-1] = '*';
			}
			if(s[i] == '*'){
				s[i] = 'o';
			}
			else{
				s[i] = '*';
			}
			Count++;
		}
	}
	if(s[strlen(s)-1]!=S[strlen(s)-1]){
		cout << 0 << endl;
	}
	else{
		cout << Count << endl;
	}
	return 0;
}


標題:帶分數

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

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

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

    類似這樣的帶分數,100 有 11 種表示法。

題目要求:

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

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

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

例如:

用戶輸入:

100

程序輸出:

11

再例如:

用戶輸入:

105

程序輸出:

6

資源約定:

峯值內存消耗 < 64M

CPU消耗  < 3000ms

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

所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。

注意:main函數需要返回0

注意:只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操作系統的特殊函數。

注意:所有依賴的函數必須明確地在源文件中 #include <xxx>, 不能通過工程設置而省略常用頭文件。

提交時,注意選擇所期望的編譯器類型。

 解題思路

該題同樣考全排列問題不再贅述。

實現代碼如下

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
bool book[10];
int arr[9], Count = 0;
double N;
void dfs(int n){
	if(n==9){
		double tmp = 0;
		for(int i = 0; i < 9; i++){
			tmp = tmp*10+arr[i];
			if(tmp > N){
				break;
			}
			else{
				double Tmp = 0;
				for(int j = i+1; j < 9; j++){
					Tmp = Tmp*10+arr[j];
					int TR = 0;
					for(int k = j+1; k < 9; k++){
						TR = TR*10+arr[k];
					}
					double ans = tmp+Tmp/TR;
					if(ans == N){
						Count++;
					}
					if(ans > N){
						break;
					} 
				}
			}
		}
	}
	else{
		for(int i = 1; i <= 9; i++){
			if(!book[i]){
				book[i] = 1;
				arr[n] = i;
				dfs(n+1);
				book[i] = 0;
			}
		}
	}
}
int main(){
	cin >> N;
	memset(book, 0, sizeof(book));
	dfs(0);
	cout << Count << endl;
	return 0;
}


標題:連號區間數

    小明這些天一直在思考這樣一個奇怪而有趣的問題:

    在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]

資源約定:

峯值內存消耗 < 64M

CPU消耗  < 5000ms

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

所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。

注意:main函數需要返回0

注意:只使用ANSI C/ANSI C++ 標準,不要調用依賴於編譯環境或操作系統的特殊函數。

注意:所有依賴的函數必須明確地在源文件中 #include <xxx>, 不能通過工程設置而省略常用頭文件。

提交時,注意選擇所期望的編譯器類型

解題思路

實現代碼如下

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
	int arr[50010], Count = 0, T;
	cin >> T;
	for(int i = 1; i <= T; i++){
		cin >> arr[i];
	}
	for(int i = 1; i <= T; i++){
		int Max = arr[i], Min = arr[i];
		for(int j = i; j <= T; j++){
			Max = max(Max, arr[j]);
			Min = min(Min, arr[j]);
			if(Max-Min == j-i)Count++;
		}
	}
	cout << Count << endl;
	return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章