第四屆“藍橋杯”全國軟件專業人才設計與創業大賽選拔賽C/C++本科B組主講解題思想


分類: 藍橋杯2013-05-0921:15 78人閱讀 評論(0) 收藏 舉報

1. 結果填空 (滿分4

題目標題: 高斯日記 

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

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

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

呢?

 高斯出生於:1777430日。

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

 高斯獲得博士學位的那天日記上標着:8113        請你算出高斯獲得博士學位的年月日。 

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

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

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

 

考場快速解題:

先看1778是閏年麼?答案是不是,所以 8113  - 365= 7748,又1779也不是,所以再減3657383,然後1780是的,所以減去3667017,又

1781,1782,1783,肯定都不是所以連減33655922,然後又是閏年,-366,再-365 - 365-365 -366 - 365 -365 -365 -366-365 -365 -365  ~ -366 -365-365 -365  1799  

78,即這一天是1799430日之後的78天,531天,-31,630天,-30,剩17天,此時即加上兩個月,爲1799630日,然後往後數17天,即爲1799716日。

 

答案即爲:1799-07-16

 

2. 結果填空 (滿分5

        標題: 馬虎的算式 

        小明是個急性子,上小學的時候經常把老師寫在黑板上的題目抄錯了。    有一次,老師出的題目是: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  這樣的算式一共有多少種呢?請你利用計算機的優勢尋找

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

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

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

 

快速解題技巧:

暴力秒吧。五重循環,絕對很快出答案。根據給的那個ab * cde = adb * ce算式,五個變量,一個判斷條件,直接跑。很方便。

 

答案爲:142

 

3. 結果填空 (滿分8

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

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

        如果我每一步只能邁上1個或2個臺階。先邁左腳,然後左右交替,最後一步是邁

        右腳,也就是說一共要走偶數步。那麼,上完39級臺階,有多少種不同的上法呢? 

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

        要求提交的是一個整數。 

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

 

快速解題技巧:

首先,踏到第i層有4種方法,分爲:用左或右腳在第i-1或第i-2層踏上。此時只需加一個判斷是左還是右腳踏的變量就可以用一個遞歸或遞推算出答案。當然你要是對遞歸有些

不放心大可用二維的,一個判斷左還是右一個維度的值存左或右腳踏上這層的方法數,來求解問題。

 

答案爲:51167078

遞歸代碼:

[cpp] view plaincopy

1.   #include <stdio.h>  

2.     

3.   int fun(int n,int flag){  

4.       if(n == 1){  

5.           if(flag == 1)  

6.           return 1;  

7.           else return 0;  

8.       }  

9.       else if(n == 2){  

10.          return 1;  

11.      }  

12.      return (fun(n-1,!flag) + fun(n - 2,!flag));  

13.  }  

14.    

15.  int main()  

16.  {  

17.      printf("%d\n",fun(39,0));  

18.      return 0;  

19.  }  




4. 結果填空 (滿分12
        
標題: 黃金連分數 

        黃金分割數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位數字,請通過瀏覽器直接提交該數字。注意:不要提交解答過程,或其它輔助說明類的內容。 

 

快速解題技巧:

此題首先明確,小數點後面100位數,不可能用某個變量來存起來,所以應當想到大數據的存儲。此題用java的大數據處理無遺會減少很多時間,因爲你節約了寫大整數的運算

函數了。這題如果一開始能聯想到斐波那契數的話再加上會java的大整數運算,那麼很快就能過了,選擇斐波那契數裏面某兩個連續的數,小的做被除數,大的做除數。利用

java的大整數,每一位存起兩數的商值,然後將餘數乘以10 再做被除數,除數不變。一直算到一百位即可。

 

當然最最快速的方法莫過於出去上個廁所拿手機出來百度一下。100位直接到手。是不是很快?!

 

答案爲:0.6180339887 4989484820 4586834365 6381177203 0917980576
2862135448 6227052604 6281890244 9707207204 1893911374

 

5. 代碼填空 (滿分5

        題目標題:前綴判斷 

        如下的代碼判斷 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;

                  returnhaystack_start;

        } 

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

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

 

快速解題技巧:

這樣的題考的就是你對指針的理解程度,將題意看懂,*needle_start的數組若是*haystack_start數組的前綴則*haystack_start的前len個字符和*needle_start數組的前len個字

符對等。而len的值即爲*needle_start數組的長度。所以什麼情況下才是真呢?一個一個的比嘛,直到某一方比完,或者出現了不等,出現了不等則不是其前綴,即返回

NULL,若比完了一方,則看被比完的是哪一方,若是*needle_start被比完了,那麼就代表它是另一數組的前綴,返回頭指針,若是*haystack_start被比完了,那麼就代表着

*haystack_start數組是*needle_start數組的前綴,即爲相反了,故不是,返回NULL

 

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

 

 

6. 代碼填空 (滿分7

        標題:三部排序 

        一般的排序有許多經典算法,如快速排序、希爾排序等。     但實際應用時,經常會或多或少有一些特殊的要求。我們沒必要套用那些經典算法,可以根據實際情況建立

        好的解法。 

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

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

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

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

        voidsort3p(int* x, int len) 

        { 

                  intp = 0;  int left = 0;  

                  intright = 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 

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

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

 

快速解題技巧:

類似快排,根據代碼拿着數組自己用手紙筆模擬走一兩趟讓他碰上0這個關鍵值,然後你就要想如何讓這個代碼實現排序,在0這個位置要加個什麼代碼,相信只要你手動運行

了一遍,你會很快得出答案的。

 

答案:p++

 

7. 程序設計(滿分4分) 

        標題:錯誤票據 

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

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

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

        你的任務是通過編程,找出斷號的ID和重號的ID     假設斷號不可能發生在最大和最小號。  

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

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

        要求程序輸出1行,含兩個整數m n,用空格分隔。其中,m表示斷號IDn表示重號ID  

        例如:用戶輸入:

        5 68 11 9  10 12 9  

        則程序輸出: 7 9  

        再例如:用戶輸入:

        164178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196172189 127 107 112 192 103 131 133 169 158  

        128102 110 148 139 157 140 195 197 

        185152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190149138 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 160167 147198 111 119  

        則程序輸出: 105 120     

        資源約定: 

        峯值內存消耗 < 64M 

        CPU消耗  < 1000ms  

        請嚴格按要求輸出,不要畫蛇添足地打印類似:請您輸入...” 的多餘內容。所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。  

        注意: main函數需要返回

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

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

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

 

快速解題技巧:

數據不大,開個數組,判斷是否輸入號碼,若輸入過了即爲重號,記下;輸入完之後一個for循環直接求出沒輸入的那個值,答案即出。

 

8. 程序設計(滿分10分) 

        題目標題:翻硬幣 

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

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

        如果同時翻轉左邊的兩個硬幣,則變爲:oooo***oooo     現在小明的問題是:如果已知了初始狀態和要達到的目標狀態,每次只能同時翻轉相鄰的兩個硬幣,那麼對特定的

        局面,最少要翻動多少次呢? 

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

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

        程序輸出: 

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

        例如:用戶輸入:

**********

o****o**** 

        程序應該輸出: 

        5 

        再例如:用戶輸入:

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

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

        程序應該輸出:

        資源約定: 

        峯值內存消耗 < 64M 

        CPU消耗  < 1000ms  

        請嚴格按要求輸出,不要畫蛇添足地打印類似:請您輸入...” 的多餘內容。所有代碼放在同一個源文件中,調試通過後,拷貝提交該源碼。  

        注意: main函數需要返回

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

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

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

 

快速解題技巧:

這題看了下別人思路,利用貪心原理,從第一個開始兩串字符串一個一個的比,不相等就翻一下,然後就相等了,就這樣一個一個的翻。最後代碼對測試用例是對的,但是是否

這就對所有測試數據都成立,也就是這個思想是不是對的,還有待考證。若哪位大神知道,還請不啻授教。

 

貪心代碼:

[cpp] view plaincopy

1.   #include <stdio.h>  

2.     

3.   #define N 1001  

4.   char s1[N],s2[N];  

5.     

6.   char become(char c){  

7.       switch(c){  

8.           case '*':return 'o';  

9.           case 'o':return '*';  

10.      }  

11.  }  

12.    

13.  int f(char *a,char *b){  

14.      int num = 0;  

15.      while(*a){  

16.          if(*a != *b){  

17.              *a = become(*a);  

18.              *(a + 1) = become(*(a + 1));  

19.              num ++;  

20.          }  

21.          a++,b++;  

22.      }  

23.      return num;  

24.  }  

25.    

26.  int main()  

27.  {  

28.      while(~scanf("%s%s",s1,s2)){  

29.          printf("%d\n",f(s1,s2));  

30.      }  

31.      return 0;  

32.  }  



9. 程序設計(滿分16分) 

        標題:帶分數 

        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函數需要返回

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

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

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

 

快速解題技巧:

除了暴力,暫時還沒想到其它好的方法。有懂的大神,還請教教小弟。

 

10. 程序設計(滿分29分) 

        標題:連號區間數 

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

        1~N的某個全排列中有多少個連號區間呢?這裏所說的連號區間的定義是:    如果區間[L, R] 裏的所有元素(即此排列的第L個到第R個元素)遞增排序後能得到一個長度

        R-L+1連續數列,則稱這個區間連號區間。 

        N很小的時候,小明可以很快地算出答案,但是當N變大的時候,問題就不是那麼簡單了,現在小明需要你的幫助。  

        輸入格式: 

        第一行是一個正整數N (1 <= N <= 50000), 表示全排列的規模。 

        第二行是N個不同的數字Pi(1 <= Pi <= N)表示這N個數字的某一全排列。  

        輸出格式: 

        輸出一個整數,表示不同連號區間的數目。  

        示例:用戶輸入:

        3 2 4 1  

        程序應輸出: 7  

        用戶輸入:

        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函數需要返回

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

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

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

 

快速解題技巧:

這樣的題,理解清楚題意,根據上面題目提示說要是連續區間,則區間裏的所有的人數排序後就是遞增的而且每次只增1,所以L-R+1是區間的長度同時也一定是這個區間裏最

大值與最小值的差值,即兩個值時相等的,因此若不相等,則就不是連續區間。想通這一點代碼一點都不難了。

 

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