2011年第二屆藍橋杯(C/C++)預賽題目及個人答案(歡迎指正)

第一題

代碼填空 (滿分3分)

神祕的三位數

有這樣一個3位數,組成它的3個數字階乘之和正好等於它本身。即:abc = a! + b! + c!

下面的程序用於搜索這樣的3位數。請補全缺失的代碼。

把填空的答案(僅填空處的答案,不包括題面)存入考生文件夾下對應題號的“解答.txt”中即可。

    int JC[] = {1,1,2,6,24,120,720,5040,40320,362880};

    int i;

    for(i=100; i<1000; i++)

    {

        int sum = 0;

        int x = i;

        while(__________)

        {

            sum += JC[x%10];

            x /= 10;

        }

        if(i==sum) printf("%d\n", i);

    }


答案:x>0



第二題

代碼填空 (滿分4分)

歌賽新規則

歌手大賽的評分規則一般是去掉一個最高分,去掉一個最低分,剩下的分數求平均。當評委較少的時候,如果我們只允許去掉一個分數,該如何設計規則呢?

有人提出:應該去掉與其餘的分數平均值相差最遠的那個分數。即“最離羣”的分數。

以下的程序用於實現這個功能。其中x存放所有評分,n表示數組中元素的個數。函數返回最“離羣”的那個分數值。請補全缺失的代碼。

把填空的答案(僅填空處的答案,不包括題面)存入考生文件夾下對應題號的“解答.txt”中即可。

double score(doublex[], int n)

{

    int i,j;

    double dif = -1;

    double bad;

    for(i=0; i<n; i++)

    {

        double sum = 0;

        for(j=0; j<n; j++)

        {

            if(________) sum += x[j];

        }

        double t = x[i] - sum / (n-1);

        if(t<0) t = -t;

        if(t>dif)

        {

            dif = t;

            bad = x[i];

            printf("%d, %f\n", i, x[i]);

        }

    }

 

    return bad;

}


答案:i!=j


第三題

代碼填空 (滿分4分)

反轉串

我們把“cba”稱爲“abc”的反轉串。

下面的代碼可以把buf中的字符反轉。其中n表示buf中待反轉的串的長度。請補充缺少的代碼。

把填空的答案(僅填空處的答案,不包括題面)存入考生文件夾下對應題號的“解答.txt”中即可。

void reverse_str(char*buf, int n)

{

    if(n<2) return;

    char tmp = buf[0];

    buf[0] = buf[n-1];

    buf[n-1] = tmp;

    _______________________________;

}


交換完第一個和倒數第一個後,又交換第二個和倒數第二個,依次進行下去。注意比如進行第二個和倒數第二個的交換時,第二個數成爲buf的第一個數,那麼倒數第二個數的位置相應減去1位,所以累計要減去2.


答案:reverse_str(buf+1, n-2)



第四題

代碼填空 (滿分5分)

n進制小數

將任意十進制正小數分別轉換成2,3,4,5,6,7,8,9進制正小數,小數點後保留8位,並輸出。例如:若十進制小數爲0.795,則輸出:

       十進制正小數0.795000 轉換成 2 進制數爲: 0.11001011

       十進制正小數0.795000 轉換成 3 進制數爲: 0.21011011

       十進制正小數0.795000 轉換成 4 進制數爲: 0.30232011

       十進制正小數0.795000 轉換成 5 進制數爲: 0.34414141

       十進制正小數0.795000 轉換成 6 進制數爲: 0.44341530

       十進制正小數0.795000 轉換成 7 進制數爲: 0.53645364

       十進制正小數0.795000 轉換成 8 進制數爲: 0.62702436

       十進制正小數0.795000 轉換成 9 進制數爲: 0.71348853

以下代碼提供了這個功能。其中,dTestNo表示待轉的十進制小數。iBase表示進制數。請填寫缺失的部分。

把填空的答案(僅填空處的答案,不包括題面)存入考生文件夾下對應題號的“解答.txt”中即可。

void fun(doubledTestNo, int iBase)

{

    int iT[8];

    int iNo;

 

    printf("十進制正小數 %f 轉換成 %d 進制數爲: ",dTestNo, iBase);

 

    for(iNo=0;iNo<8;iNo++)

    {

        dTestNo *= iBase;

        iT[iNo] = ________________;

        if(___________________) dTestNo -= iT[iNo];

    }

   

    printf("0.");

    for(iNo=0; iNo<8; iNo++) printf("%d", iT[iNo]);

    printf("\n");

}

 

void main ( )

{  

    double dTestNo= 0.795;

    int iBase;

 

    for(iBase=2;iBase<=9;iBase++)

        fun(dTestNo,iBase);

    printf("\n");

}


答案:

(int)dTestNo

dTestNo



第五題

代碼填空 (滿分6分)

輪換

串“abcd”每個字符都向右移位,最右的移動到第一個字符的位置,就變爲“dabc”。這稱爲對串進行位移=1的輪換。同理,“abcd”變爲:“cdab”則稱爲位移=2的輪換。

下面的代碼實現了對串s進行位移爲n的輪換。請補全缺失的代碼。

把填空的答案(僅填空處的答案,不包括題面)存入考生文件夾下對應題號的“解答.txt”中即可。

void shift(char* s, intn)

{

    char* p;

    char* q;

    int len = strlen(s);

    if(len==0) return;

    if(n<=0 || n>=len) return;

 

    char* s2 = (char*)malloc(_________);

    p = s;

    q = s2 + n % len;

    while(*p)

    {  

        *q++ = *p++;

        if(q-s2>=len)

        {

            *q = ___________;

            q = s2;

        }

    }

    strcpy(s,s2);

    free(s2);

}


答案:

(len+1)*sizeof(char)

'\0'



第六題

代碼填空 (滿分9分)

中獎計算

某抽獎活動的規則是:每位參與者在紙上寫下一個8位數的號碼。最後通過搖獎的辦法隨機產生一個8位數字。參與者寫下的數字中最多有多少個連續位與開獎號碼中的相同,則稱爲中了幾個號。

例如:小張寫的數字是:12345678,而開獎號碼是:42347856。則稱小張中了3個號,因爲其中最長的相同連續位是:“234”。如果小張寫的是:87654321,則他只中了一個號。

下面的代碼根據傳入的參數,返回中了幾個號。其中:a表示被評價的號碼,b表示搖號產生的數字。請填寫缺少的代碼。

把填空的答案(僅填空處的答案,不包括題面)存入考生文件夾下對應題號的“解答.txt”中即可。

int g(int a, int b)

{

    char sa[]="00000000";

    char sb[]="00000000";

    int n = 0;

    int i,j;

 

    sprintf(sa,"%8d",a);

    sprintf(sb,"%8d",b);

    for(i=0; i<8; i++)

    {

        for(j=1; j<=8-i; j++)

        {

            char t = ________;

            sa[i+j] = 0;

            if(strstr(sb, sa+i))

            {

                if(j>n) _________;

            }

            sa[i+j] = t;

        }

    }

 

    return n;

}


答案:

sa[i+j]

n=j



第七題

代碼填空 (滿分10分)

概率問題

某個袋子中有紅球m個,白球n個。現在要從中取出x個球。那麼紅球數目多於白球的概率是多少呢?

下面的代碼解決了這個問題。其中的y表示紅球至少出現的次數。

這與前文的問題是等價的。因爲如果取30個球,要求紅球數大於白球數,則等價於至少取出16個紅球。請根據僅存的線索,判斷程序邏輯,並補全缺少的代碼。

把填空的答案(僅填空處的答案,不包括題面)存入考生文件夾下對應題號的“解答.txt”中即可。

/*

   m: 袋中紅球的數目

   n: 袋中白球的數目

   x: 需要取出的數目

   y: 紅球至少出現的次數

*/

double pro(int m, intn, int x, int y)

{

    if(y>x) return 0;

    if(y==0) return 1;

    if(y>m) return 0;

    if(x-n>y) return 1;

    double p1 = _______________________;

    double p2 = _______________________;

    return (double)m/(m+n) * p1 + (double)n/(m+n) * p2;

}


答案:

pro(m-1,n,x-1,y-1)

pro(m,n-1,x-1,y)



第八題

程序設計(滿分15分)

方陣的主對角線之上稱爲“上三角”。

請你設計一個用於填充n階方陣的上三角區域的程序。填充的規則是:使用1,2,3….的自然數列,從左上角開始,按照順時針方向螺旋填充。

例如:當n=3時,輸出:

1 2 3

6 4

5

當n=4時,輸出:

1  2 3 4

9 10 5

8  6

7

當n=5時,輸出:

  1 2  3  4  5

 12 13 14 6

 11 15  7

 10  8

  9

程序運行時,要求用戶輸入整數n(3~20)

程序輸出:方陣的上三角部分。

要求格式:每個數據寬度爲4,右對齊。

 

要求考生把所有函數寫在一個文件中。調試好後,存入與考生文件夾下對應題號的“解答.txt”中即可。相關的工程文件不要拷入。

對於編程題目,要求選手給出的解答完全符合ANSI C標準,不能使用c++特性;不能使用諸如繪圖、中斷調用等硬件相關或操作系統相關的API。


三角螺旋陣的規律是順時針數字從1開始遞增的,因此我們也可以按照一圈一圈來將依次遞增的數賦給一個二維數組,然後輸出倒三角的數組即可。

<span style="font-size:14px;">#include<stdio.h>  
int a[20][20];  
int main()  
{  
    int n;  
    while(~scanf("%d",&n))  
    {  
        int i,j,circle=1;//circle記錄進行到了第幾圈  
        int pos=1;  
        while(pos<=n*(n+1)/2)  
        {  
            for(i=circle,j=circle; j<=n-(circle-1)*2; j++)//橫向向右賦值  
                a[i][j]=pos++;  
            for(i=circle+1,j=n-(circle-1)*2-1; i<=n-(circle-1)*2&&j>=circle; i++,j--)//對角線左下向賦值  
                a[i][j]=pos++;  
            for(i=n-(circle-1)*2-1,j=circle; i>=circle+1; i--)//豎向向上賦值  
                a[i][j]=pos++;  
            circle++;  
        }  
        for(i=1; i<=n; i++)//倒三角輸出  
        {  
            for(j=1; j<=n-i+1; j++)  
                printf("%4d",a[i][j]);  
            printf("\n");  
        }  
    }  
    return 0;  
}  </span>




第九題

程序設計(滿分16分)

公司發了某商店的購物券1000元,限定只能購買店中的m種商品。每種商品的價格分別爲m1,m2,…,要求程序列出所有的正好能消費完該購物券的不同購物方法。

程序輸入:

第一行是一個整數m,代表可購買的商品的種類數。

接下來是m個整數,每個1行,分別代表這m種商品的單價。

程序輸出:

       第一行是一個整數,表示共有多少種方案

       第二行開始,每種方案佔1行,表示對每種商品購買的數量,中間用空格分隔。

例如:

       輸入:

2

200

300

則應輸出:

2

2  2

5  0

       輸入:

2

500

800

則應輸出:

1

2  0

 

要求考生把所有函數寫在一個文件中。調試好後,存入與考生文件夾下對應題號的“解答.txt”中即可。相關的工程文件不要拷入。

對於編程題目,要求選手給出的解答完全符合ANSI C標準,不能使用c++特性;不能使用諸如繪圖、中斷調用等硬件相關或操作系統相關的API。


遞歸思路,具體見代碼註解。

<span style="font-size:14px;">#include<stdio.h>
#include<string.h>
int m;//物品數
int p[100];//價格
int ans[100][100];//ans[i][j]表示第i個方案中第j個物品被選數
int num[100];//num[i]表示第i件物品被選的個數
int cas=0;//方案數
int money=0;//花的錢
void buy(int n)//n表示當前搜索到的物品編號
{
    if(money>1000||n>=m)//當花的錢超過預算或者所有的物品都已遍歷過了,不再繼續搜索下去
        return ;
    if(money==1000)//當花的錢正好爲1000,滿足要求
    {
        for(int i=0; i<m; i++)
            ans[cas][i]=num[i];
        cas++;
        return ;
    }
    num[n]++;//選該物品
    money+=p[n];
    buy(n);//可以繼續選該物品
    num[n]--;//不選該物品,前面加的要減去
    money-=p[n];//錢也相應的減
    buy(n+1);//選下一個物品
}
int main()
{
    scanf("%d",&m);
    for(int i=0; i<m; i++)
        scanf("%d",&p[i]);
    memset(num,0,sizeof(num));
    buy(0);
    printf("%d\n",cas);
    for(int i=0; i<cas; i++)
    {
        for(int j=0; j<m; j++)
            printf("%d ",ans[i][j]);
        printf("\n");
    }
    return 0;
}</span><span style="color:#ff0000;font-size: 18px;">
</span>




第十題

程序設計(滿分28分)

一種Playfair密碼變種加密方法如下:首先選擇一個密鑰單詞(稱爲pair)(字母不重複,且都爲小寫字母),然後與字母表中其他字母一起填入至一個5x5的方陣中,填入方法如下:

1.首先按行填入密鑰串。

2.緊接其後,按字母序按行填入不在密鑰串中的字母。

3.由於方陣中只有25個位置,最後剩下的那個字母則不需變換。

如果密鑰爲youandme,則該方陣如下: 

y o u a n

d m e b c

f g h i j

k l p q r

s t v w x

在加密一對字母時,如am,在方陣中找到以這兩個字母爲頂點的矩形(紅色字體):

y o u a n

d m e b c

f g h i j

k l p q r

s t v w x

 

這對字母的加密字母爲該矩形的另一對頂點,如本例中爲ob。

請設計程序,使用上述方法對輸入串進行加密,並輸出加密後的串。

另外有如下規定:

1、一對一對取字母,如果最後只剩下一個字母,則不變換,直接放入加密串中;

2、如果一對字母中的兩個字母相同,則不變換,直接放入加密串中;

3、如果一對字母中有一個字母不在正方形中,則不變換,直接放入加密串中;

4、如果字母對出現在方陣中的同一行或同一列,如df或hi,則只需簡單對調這兩個字母,即變換爲fd或ih;

5、如果在正方形中能夠找到以字母對爲頂點的矩形,假如字母對爲am,則該矩形的另一對頂點字母中,與a同行的字母應在前面,在上例中應是ob;同樣若待變換的字母對爲ta,則變換後的字母對應爲wo;

6、本程序中輸入串均爲小寫字母,並不含標點、空格或其它字符。

解密方法與加密相同,即對加密後的字符串再加密,將得到原始串。

要求輸入形式如下:

從控制檯輸入兩行字符串,第一行爲密鑰單詞(長度小於等於25),第二行爲待加密字符串(長度小於等於50),兩行字符串末尾都有一個回車換行符,並且兩行字符串均爲小寫字母,不含其它字符。

在標準輸出上輸出加密後的字符串。

例如,若輸入:

youandme

welcometohangzhou

則表示輸入的密鑰單詞爲youandme,形成的正方形如上所示;待加密字符串爲welcometohangzhou。在正方形中可以找到以第一對字母we爲頂點的矩形,對應另一對頂點字母爲vb,因此加密後爲vb,同理可找到與字母對lc,et,oh,ho對應的頂點字母對。而字母對om位於上述正方形中的同一列,所以直接以顛倒這兩個字母來加密,即爲mo,字母對an同理。字母對gz中的z不在上述正方形中,因此原樣放到加密串中。最後剩一個字母u也原樣輸出。

因此輸出的結果爲:

vbrmmomvugnagzguu

 

要求考生把所有函數寫在一個文件中。調試好後,存入與考生文件夾下對應題號的“解答.txt”中即可。相關的工程文件不要拷入。

對於編程題目,要求選手給出的解答完全符合ANSI C標準,不能使用c++特性;不能使用諸如繪圖、中斷調用等硬件相關或操作系統相關的API。


#include<stdio.h>
#include<string.h>
char a[5][5];
char s1[25],s2[25];
int l;
bool judge(char ch)//判斷該字符是否在密鑰字符串中
{
    int sum=0;
    for(int i=0; i<l; i++)
    {
        if(ch!=s1[i])
            sum++;
    }
    if(sum==l)
        return 1;
    return 0;
}
bool judge2(char ch)//判斷該字符是否在密鑰矩陣中
{
    int sum=0;
    for(int i=0; i<5; i++)
    {
        for(int j=0; j<5; j++)
        {
            if(ch!=a[i][j])
                sum++;
        }
    }
    if(sum==25)
        return 1;
    return 0;
}
void posi(char ch,int &x,int &y)//該字符在密鑰矩陣中對應的座標
{
    for(int i=0; i<5; i++)
    {
        for(int j=0; j<5; j++)
        {
            if(a[i][j]==ch)
            {
                x=i;
                y=j;
            }
        }
    }
}
bool posijudge(char c1,char c2)//判斷兩字符是否在同一行或同一列
{
    int x1,x2,y1,y2;
    posi(c1,x1,y1);
    posi(c2,x2,y2);
    if(x1==x2||y1==y2)
        return 1;
    return 0;
}
int main()
{
    scanf("%s%s",s1,s2);
    l=strlen(s1);
    int pos=0;
    char ch='a';
    for(int i=0; i<5; i++)//將密鑰字符串變爲密鑰矩陣
    {
        for(int j=0; j<5; j++)
        {
            if(s1[pos]!='\0')
            {
                a[i][j]=s1[pos];
                pos++;
            }
            else
            {
                while(!judge(ch))
                {
                    ch++;
                }
                a[i][j]=ch;
                ch++;
            }
        }
    }
    int n=strlen(s2);
    char t1,t2;
    char ans[25];
    for(int i=0; i<n; i+=2)
    {
        t1=s2[i];
        t2=s2[i+1];
        if(t1==t2||t2=='\0')//情況1、2(對應規定1、2)
        {
            ans[i]=t1;
            ans[i+1]=t2;
        }
        else if(judge2(t1)||judge2(t2))//情況3(對應規定3)
        {
            ans[i]=t1;
            ans[i+1]=t2;
        }
        else if(posijudge(t1,t2))//情況4(對應規定4)
        {
            ans[i]=t2;
            ans[i+1]=t1;
        }
        else//其它正常情況
        {
            int x1,x2,y1,y2;
            posi(t1,x1,y1);
            posi(t2,x2,y2);
            ans[i]=a[x1][y2];
            ans[i+1]=a[x2][y1];
        }
    }
    printf("%s\n",ans);
    return 0;
}


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