2014藍橋杯決賽試題及答案

猜燈謎

A村的元宵節燈會上有一迷題:

請猜謎 * 請猜謎 = 請邊賞燈邊猜

小明想,一定是每個漢字代表一個數字,不同的漢字代表不同的數字。

請你用計算機按小明的思路算一下,然後提交“請猜謎”三個字所代表的整數即可。

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

注意:只提交一個3位的整數,不要寫其它附加內容,比如:說明性的文字。

答案:897

直接for加判斷就好

加密

在對文本進行簡單加密的時候,可以選擇用一個n位的二進制數,對原文進行異或運算。
解密的方法就是再執行一次同樣的操作。

加密過程中n位二進制數會循環使用。並且其長度也可能不是8的整數倍。

下面的代碼演示瞭如何實現該功能。

請仔細閱讀,填寫空缺的代碼(下劃線部分)。

注意:請把填空的答案(僅填空處的答案,不包括題面)存入考生文件夾下對應題號的“解答.txt”中即可。
直接寫在題面中不能得分。

void f(char* buf, unsigned char* uckey, int n)
{
    int i;
    for(i=0; i<n; i++)
        buf[i] = buf[i] ^ uckey[i];
}

int main(int argc, char* argv[])
{
    char p[] = "abcd中國人123";  // 待加密串

    char* key = "11001100010001110";  //以串的形式表達的密匙,運算時要轉換爲按位存儲的形式。

    int np = strlen(p);
    int nk = strlen(key);
    unsigned char* uckey = (unsigned char*)malloc(np);  

    // 密匙串需要按位的形式循環拼入 uckey中
    int i;
    for(i=0; i<np*8; i++)
    {
        if(key[i%nk]=='1')
            ____________________________________________;  // 填空1
        else
            ____________________________________________;  // 填空2

    }

    f(p, uckey, strlen(p));
    f(p, uckey, strlen(p));

    printf("%s\n", p);

    free(uckey);

    return 0;
}

答案:



 // 密匙串需要按位的形式循環拼入 uckey中  
    int i;  
    for(i=0; i<np*8; i++)  
    {  
        if(key[i%nk]=='1')  
        {  
            uckey[i / 8] = (uckey[i / 8] << 1) | 0x01;  // 填空1  
            //uckey[i/8] |= (unsigned char)0x80 >> (i%8); //標準答案  
        }  
        else  
        {  
            uckey[i / 8] = uckey[i / 8] << 1;  // 填空2  
            //uckey[i/8] &= ~((unsigned char)0x80 >> (i%8)); //標準答案  
        }  

    }  

公倍數

爲什麼1小時有60分鐘,而不是100分鐘呢?這是歷史上的習慣導致。
但也並非純粹的偶然:60是個優秀的數字,它的因子比較多。
事實上,它是1至6的每個數字的倍數。即1,2,3,4,5,6都是可以除盡60。

我們希望尋找到能除盡1至n的的每個數字的最小整數。

不要小看這個數字,它可能十分大,比如n=100, 則該數爲:
69720375229712477164533808935312303556800

請編寫程序,實現對用戶輸入的 n (n<100)求出1~n的最小公倍數。

例如:
用戶輸入:
6
程序輸出:
60

用戶輸入:
10
程序輸出:
2520

要求考生把所有函數寫在一個文件中。調試好後,存入與考生文件夾下對應題號的“解答.txt”中即可。
相關的工程文件不要拷入。
對於編程題目,要求選手給出的解答完全符合ANSI C標準,不能使用c++特性;
不能使用諸如繪圖、中斷調用等硬件相關或操作系統相關的API。

答案:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

const int N = 105;
int n;
int a[N][50];
int b[N] = {0};

void multiply()
{
    int i,j,k;
    memset(a,0,sizeof(a));
    for(i=3; i<=100; i++)
    {
        /*
        下面的是直接按平常的乘法,乘數的一位乘以被乘數的每一位並處理進位;另外是乘數整體乘以被乘數的每一位最後統一處理進位
        */
        int temp = 0; 
        a[i][0] = 1;//很重要 
        for(j=2; j<=i; j++)
        {
            int  c = 0; 
            for(k=0; k<50; k++)//最大不超過160位 ,安的是100!,最後除以3等50 
            {
                temp = a[i][k]*b[j] + c;
                a[i][k] = temp%1000;
                c = temp/1000;
            }          
        }
    }
}

void printData(int n)
{
    int i,j,k;
    for(i=49; i>=0; i--)
    if(a[n][i])
        break;
    cout<<a[n][i];//第一個不輸出前導0 
    for(j=i-1; j>=0; j--)
        printf("%03d",a[n][j]);
    cout<<endl;   
}

int main()
{
    int i, j, k;
    for(i=0; i<N; i++)
            b[i] = i;
    for(i=2; i<N; i++)
        for(j=i+1; j<=N; j++)
        {
            if(b[j]%b[i]==0)
                b[j] /= b[i];
            //cout<<b[j]<<endl;
        }
    //for(i=0; i<100; i++)
      //  cout<<b[i]<<endl;
    //while(1);
    multiply();

    while(cin>>n)
    {

        if(n==1||n==2)
        {
            cout<<n<<endl;
            continue;
        }

        printData(n);
    }
    return 0;
}

高僧鬥法

古時喪葬活動中經常請高僧做法事。儀式結束後,有時會有“高僧鬥法”的趣味節目,以舒緩壓抑的氣氛。
節目大略步驟爲:先用糧食(一般是稻米)在地上“畫”出若干級臺階(表示N級浮屠)。又有若干小和尚隨機地“站”在某個臺階上。最高一級臺階必須站人,其它任意。
兩位參加遊戲的法師分別指揮某個小和尚向上走任意多級的臺階,但會被站在高級臺階上的小和尚阻擋,不能越過。兩個小和尚也不能站在同一臺階,也不能向低級臺階移動。
兩法師輪流發出指令,最後所有小和尚必然會都擠在高段臺階,再也不能向上移動。輪到哪個法師指揮時無法繼續移動,則遊戲結束,該法師認輸。
對於已知的臺階數和小和尚的分佈位置,請你計算先發指令的法師該如何決策才能保證勝出。
輸入數據爲一行用空格分開的N個整數,表示小和尚的位置。臺階序號從1算起,所以最後一個小和尚的位置即是臺階的總數。(N<100, 臺階總數<1000)
輸出爲一行用空格分開的兩個整數: A B, 表示把A位置的小和尚移動到B位置。若有多個解,輸出A值較小的解,若無解則輸出-1。
例如:
用戶輸入:
1 5 9
則程序輸出:
1 4

再如:
用戶輸入:
1 5 8 10
則程序輸出:
1 3

資源約定:
峯值內存消耗 <64M

CPU消耗 < 1000ms

答案:(好像用到了尼姆定理)

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<limits.h>
using namespace std;

int t[1111];
int b[1111];
int c[1111];

void xiazi(int sum)
{
    for(int i= 1; i< sum; i++)
        for(int j= 1; j<= b[i]; j++)
        {
            int xixi;
            if(i%2)
                xixi= c[i]^(b[i]-j);    
            else
                xixi= c[i-1]^(b[i-1]+j);
            if(xixi==0)
            {
                printf("%d %d\n",t[i],t[i]+j);  
                return; 
            }
        }
    printf("-1\n");
    return; 
}


int main()
{
    int a;
    char ch;
    scanf("%d%c",&a,&ch);
    int sum= 1;
    t[sum]= a;
    c[0]= 0;
    while(ch!='\n')
    {
        scanf("%d%c",&a,&ch);
        sum++;
        t[sum]= a;
    }
    sort(t+1, t+ sum + 1);
    for(int i= 2; i<= sum; i++)
    {
        b[i-1]= t[i]- t[i-1] - 1;
        if((i-1)%2)
            c[0]= c[0]^b[i-1]; 
    }
    for(i= 1; i< sum; i+=2)
        c[i]= c[0]^b[i];
    if(c[0]==0)
        printf("-1\n");
    else
        xiazi(sum); 
    return 0;
}

方格填數

如下圖所示,3 x 3 的格子中填寫了一些整數。
+–*–+–+
|10* 1|52|
+–**–+
|20|30* 1|
*–+
| 1| 2| 3|
+–+–+–+
我們沿着圖中的星號線剪開,得到兩個部分,每個部分的數字和都是60。
本題的要求就是請你編程判定:對給定的m x n 的格子中的整數,是否可以分割爲兩個部分,使得這兩個區域的數字和相等。
如果存在多種解答,請輸出包含左上角格子的那個區域包含的格子的最小數目。
如果無法分割,則輸出 0。

這裏寫圖片描述

這裏寫圖片描述
輸入格式
程序先讀入兩個整數 m n 用空格分割 (m,n<10)。
表示表格的寬度和高度。
接下來是n行,每行m個正整數,用空格分開。每個整數不大於10000。
輸出格式
輸出一個整數,表示在所有解中,包含左上角的分割區可能包含的最小的格子數目。

樣例輸入1
3 3
10 1 52
20 30 1
1 2 3
樣例輸出1
3

樣例輸入2
4 3
1 1 1 1
1 30 80 2
1 1 1 100
樣例輸出2
10

答案:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define N 10

int map[N][N]={0};
int vis[N][N];
int count=0;//記錄解得節點數
int mincount=1000;//記錄最小的節點數
int result=0;//記錄搜索過程中的結果和
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int half;

void mysearch(int i,int j,int n,int m);//回溯法進行搜索

int main()
{
    int m,n; //n:行,m:列
    int i,j,sum=0;
    int max=-1;
    scanf("%d%d",&m,&n);
    for(i=0;i<n;i++)
    {
        for (j=0;j<m;j++)
        {
            scanf("%d",&map[i][j]);
            if (max<map[i][j])
            {
                max=map[i][j];
            }
            sum+=map[i][j];
        }
    }
    half=sum/2;
    if(max>half) //最大值大於全體數字的一般,無解
    {
        printf("0\n");
        return 0;
    }

    memset(vis,0,sizeof(vis));
    i=j=0;
    mysearch(i,j,n,m);
    system("pause");
    return 0;
}

void mysearch(int i,int j,int n,int m) //回溯法進行搜索
{
    int x,y,newx,newy;   
    int r;
    x=i;
    y=j;

    if (i<0 || i>=n || j<0 || j>=m)
    {
        return;
    }

    if(vis[x][y]==0 && result+map[x][y] <= half)
    {
        printf("(%d,%d)\n",x,y);
        result+=map[x][y];
        vis[x][y]=1;
        count++;
    }
    else
    {
        return;
    }
    if (result==half)
    {

        if (count>n*m/2)
        {
            printf("%d\n",n*m-count);
        }
        else
        {
            printf("%d\n",count);
        }
        exit(0);
    }

    for (r=0;r<4;r++)
    {
        newx=x+dx[r];
        newy=y+dy[r];

        mysearch(newx,newy,n,m);
    }

    vis[x][y]=0;
    result=result-map[x][y];
    count--;
    return;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章