1. 程式人生 > >2013年第四屆藍橋杯試題(C/C++本科B組)

2013年第四屆藍橋杯試題(C/C++本科B組)

1

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



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


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


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


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


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


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


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

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

答案:1799-07-16

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>

const int inf = 0x3f3f3f3f;//1061109567
typedef long long ll;
using namespace std;

int mon[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

bool isleap(int year)
{
    if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
        return true;
    return false;
}

int main()
{
    int year = 1777;
    int month,day;
    int sum = 8113 - 245 - 1;//到這一年年底的時候剩餘的時間,減1是因為出生的時候也算一天
    int sum1;
    while(true)
    {
        if(isleap(year+1))
        {
            sum1 = 366;
        }
        else
        {
            sum1 = 365;
        }
        if(sum < sum1)
        {
            year++;
            break;
        }
        else
        {
            year++;
            sum -= sum1;
        }
    }
    if(isleap(year))
    {
        mon[2]++;
    }
    for(int i=1; i<=12; i++)
    {
        if(sum > mon[i])
        {
            sum -= mon[i];
        }
        else
        {
            month = i;
            break;
        }
    }
    day = sum;
    printf("%d %d %d\n",year,month,day);
    return 0;
}

2

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


    有一次,老師出的題目是: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 這樣的算式一共有多少種呢?




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


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




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

答案:142(簡單回溯一下就行)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>

const int inf = 0x3f3f3f3f;//1061109567
typedef long long ll;
using namespace std;

int visit[10] = {0};
int a[5];
int sum = 0;

void dfs(int cur)
{
    if(cur == 5)
    {
        int sum1 = a[0] * 10 + a[1];
        int sum2 = a[2] * 100 + a[3] * 10 + a[4];
        int sum3 = a[0] * 100 + a[3] * 10 + a[1];
        int sum4 = a[2] * 10 + a[4];
        if(sum1 * sum2 == sum3 * sum4)
        {
            sum++;
        }
        return;
    }
    for(int i=1; i<=9; i++)
    {
        if(!visit[i])
        {
            visit[i] = 1;
            a[cur] = i;
            dfs(cur+1);
            visit[i] = 0;
        }
    }
}

int main()
{
    dfs(0);
    printf("%d\n",sum);
    return 0;
}

3

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


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


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


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


要求提交的是一個整數。
注意:不要提交解答過程,或其它的輔助說明文字。

答案:51167078

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>

const int inf = 0x3f3f3f3f;//1061109567
typedef long long ll;
using namespace std;

int dp[40][2];//第一維表示第幾節臺階,第二維0表示踏上第i階臺階是是左腳,1表示是右腳

int main()
{
    dp[1][0] = 1;
    dp[1][1] = 0;
    dp[2][0] = 1;
    dp[2][1] = 1;
    for(int i=3; i<=39; i++)
    {
        dp[i][1] = dp[i-1][0] + dp[i-2][0];
        dp[i][0] = dp[i-1][1] + dp[i-2][1];
    }
    printf("%d\n",dp[39][1]);
    return 0;
}
4

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

答案:

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;

return haystack_start;
}




請分析程式碼邏輯,並推測劃線處的程式碼,通過網頁提交。
注意:僅把缺少的程式碼作為答案,千萬不要填寫多餘的程式碼、符號或說明文字!!

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

6

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


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


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


    使得負數都靠左端,正數都靠右端,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++

剩下的題本部落格都有,單獨寫出來了