1. 程式人生 > >2015年藍橋杯省賽C/C++ A組題解(含題目)

2015年藍橋杯省賽C/C++ A組題解(含題目)

1. 方程整數解

方程: a^2 + b^2 + c^2 = 1000
這個方程有整數解嗎?有:a,b,c=6,8,30 就是一組解。
你能算出另一組合適的解嗎?
請填寫該解中最小的數字。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。

列舉

#include <bits/stdc++.h>
using namespace std;

int main()
{
    for (int i=1;i<=33;i++) {
        for (int j=i;j<=33;j++) {
            for
(int k=j;k<=33;k++) { if (i*i+j*j+k*k==1000) { printf("%d %d %d\n",i,j,k); } } } } return 0; }

答案:10

2. 星系炸彈

在X星系的廣袤空間中漂浮著許多X星人造“炸彈”,用來作為宇宙中的路標。
每個炸彈都可以設定多少天之後爆炸。
比如:阿爾法炸彈2015年1月1日放置,定時為15天,則它在2015年1月16日爆炸。
有一個貝塔炸彈,2014年11月9日放置,定時為1000天,請你計算它爆炸的準確日期。
請填寫該日期,格式為 yyyy-mm-dd
即4位年份2位月份2位日期。比如:
2015-02-19
請嚴格按照格式書寫。不能出現其它文字或符號。

想一下,我們用的可是一臺電腦!寫這個程式的話實在是太費時間了。

Step1.

複製“2014年11月9日”,貼上到excel,並把單元格格式改成日期
這裡寫圖片描述

Step2.

移動到A2,輸入”=SUM(A1,1000)”,按一下回車
這裡寫圖片描述

歐了 =。= 開心不
答案:2017-08-05

3. 奇妙的數字

小明發現了一個奇妙的數字。它的平方和立方正好把0~9的10個數字每個用且只用了一次。
你能猜出這個數字是多少嗎?
請填寫該數字,不要填寫任何多餘的內容。

列舉+模擬

#include <bits/stdc++.h>
using namespace
std; int b[10]; void solu(int x,int b[]) { while (x) { b[x%10]++; x/=10; } } int main() { for (int i=1,j;i<9999;i++) { memset(b,0,sizeof(b)); solu(i*i,b); solu(i*i*i,b); for (j=0;j<=9;j++) if (b[j]!=1) break; //每個b[i]都等於1,j才會大於9 if (j>9) { printf("%d\n",i); break; } } return 0; }

答案:69

4. 格子中輸出

StringInGrid函式會在一個指定大小的格子中列印指定的字串。
要求字串在水平、垂直兩個方向上都居中。
如果字串太長,就截斷。
如果不能恰好居中,可以稍稍偏左或者偏上一點。
下面的程式實現這個邏輯,請填寫劃線部分缺少的程式碼。

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

void StringInGrid(int width, int height, const char* s)
{
    int i,k;
    char buf[1000];
    strcpy(buf, s);
    if(strlen(s)>width-2) buf[width-2]=0;

    printf("+");
    for(i=0;i<width-2;i++) printf("-");
    printf("+\n");

    for(k=1; k<(height-1)/2;k++){
        printf("|");
        for(i=0;i<width-2;i++) printf(" ");
        printf("|\n");
    }

    printf("|");

    printf("%*s%s%*s",__________________________________);  //填空

    printf("|\n");

    for(k=(height-1)/2+1; k<height-1; k++){
        printf("|");
        for(i=0;i<width-2;i++) printf(" ");
        printf("|\n");
    } 

    printf("+");
    for(i=0;i<width-2;i++) printf("-");
    printf("+\n");
}

int main()
{
    StringInGrid(20,6,"abcd1234");
    return 0;
}

對於題目中資料,應該輸出:

+------------------+
|                  |
|     abcd1234     |
|                  |
|                  |
+------------------+

注意:只填寫缺少的內容,不要書寫任何題面已有程式碼或說明性文字。

很明顯,填空的上面是輸出上半部分,下面是輸出下半部分,所以我們填的這個就是正中間那行。
要做這題首先要知道%*s是個什麼。。。我也不知道啊
反正當年是沒填出的居多 輸出控制符資料
也就是說碰到*的時候我們要額外給一個整型引數控制寬度。

我們看到第9行,buf已經完成了截斷,而s沒有截斷,所以我們要用也只能用buf。
然後我們算出左邊右邊的寬度,值得注意的是,左右的寬度表示式是不一樣的。
因為題目裡說了不對稱是要靠左,可以把abcd1234最後的4去掉看看效果。
感覺查了這麼多部落格都沒一個人填對的。。。唉= =

答案:(width-strlen(buf)-2)/2,"",buf,(width-strlen(buf)-2+1)/2,""

5. 九陣列分數

1,2,3…9 這九個數字組成一個分數,其值恰好為1/3,如何組法?
下面的程式實現了該功能,請填寫劃線部分缺失的程式碼。

#include <stdio.h>

void test(int x[])
{
    int a = x[0]*1000 + x[1]*100 + x[2]*10 + x[3];
    int b = x[4]*10000 + x[5]*1000 + x[6]*100 + x[7]*10 + x[8];

    if(a*3==b) printf("%d / %d\n", a, b);
}

void f(int x[], int k)
{
    int i,t;
    if(k>=9){
        test(x);
        return;
    }

    for(i=k; i<9; i++){
        {t=x[k]; x[k]=x[i]; x[i]=t;}
        f(x,k+1);
        _________________________________ // 填空處
    }
}

int main()
{
    int x[] = {1,2,3,4,5,6,7,8,9};
    f(x,0);  
    return 0;
}

注意:只填寫缺少的內容,不要書寫任何題面已有程式碼或說明性文字。

這主要考的是回溯的基本概念 回溯資料
簡單的說這一次做的改變肯定要復原。

答案:{t=x[k]; x[k]=x[i]; x[i]=t;}

6. 牌型種數

小明被劫持到X賭城,被迫與其他3人玩牌。
一副撲克牌(去掉大小王牌,共52張),均勻發給4個人,每個人13張。
這時,小明腦子裡突然冒出一個問題:
如果不考慮花色,只考慮點數,也不考慮自己得到的牌的先後順序,自己手裡能拿到的初始牌型組合一共有多少種呢?
請填寫該整數,不要填寫任何多餘的內容或說明文字。

dfs,當然首先要知道每個數字都有四張牌。

#include <bits/stdc++.h>
using namespace std;

int cnt[15],ans=0;

void dfs(int dep,int last)
{
    if (dep>13) {
        ans++;
        return;
    }
    for (int i=last;i<=13;i++) {
        if (cnt[i]<4) {
            cnt[i]++;
            dfs(dep+1,i);
            cnt[i]--;
        }
    }
}

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

答案:3598180

7. 手鍊樣式

小明有3顆紅珊瑚,4顆白珊瑚,5顆黃瑪瑙。
他想用它們串成一圈作為手鍊,送給女朋友。
現在小明想知道:如果考慮手鍊可以隨意轉動或翻轉,一共可以有多少不同的組合樣式呢? 請你提交該整數。不要填寫任何多餘的內容或說明性的文字。

dfs寫起來比較難受,這題就用next_permutation next_permutation參考資料
本來想先用一個最樸素的方法試一試,結果很快就出來了。
所以只要把所有答案都記錄下來,每次都正反判斷一遍即可。

#include <bits/stdc++.h>
using namespace std;

int res[10000][12],a[12];

bool same(int a[],int b[])
{
    for (int k=0;k<12;k++) {
        bool f=true;
        for (int i=0;i<12;i++) {
            if (a[i]!=b[(i+k)%12]) {
                f=false;
                break;
            }
        }
        if (f) return true;
        f=true;
        for (int i=0;i<12;i++) {
            if (a[11-i]!=b[(i+k)%12]) {
                f=false;
                break;
            }
        }
        if (f) return true;
    }
    return false;
}

int main()
{
    int ans=0;
    a[0]=a[1]=a[2]=1;
    a[3]=a[4]=a[5]=a[6]=2;
    a[7]=a[8]=a[9]=a[10]=a[11]=3;
    do {
        bool ok=true;
        for (int i=1;i<=ans;i++) {
            if (same(res[i],a)) {
                ok=false;
                break;
            }
        }
        if (ok) {
            ans++;
            for (int i=0;i<12;i++) {
                res[ans][i]=a[i];
            }
        }
    } while (next_permutation(a,a+12));
    printf("%d\n",ans);
    return 0;
}

8. 飲料換購

樂羊羊飲料廠正在舉辦一次促銷優惠活動。樂羊羊C型飲料,憑3個瓶蓋可以再換一瓶C型飲料,並且可以一直迴圈下去(但不允許暫借或賒賬)。

請你計算一下,如果小明不浪費瓶蓋,儘量地參加活動,那麼,對於他初始買入的n瓶飲料,最後他一共能喝到多少瓶飲料。

輸入:一個整數n,表示開始購買的飲料數量(0 < n < 10000)
輸出:一個整數,表示實際得到的飲料數

例如:
使用者輸入:
100
程式應該輸出:
149

使用者輸入:
101
程式應該輸出:
151

資源約定:
峰值記憶體消耗 < 256M
CPU消耗 < 1000ms

請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入…” 的多餘內容。
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include , 不能通過工程設定而省略常用標頭檔案。
提交時,注意選擇所期望的編譯器型別。

簡單模擬

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int s,n;
    scanf("%d",&n);
    s=n;
    while (n>=3) {
        s+=n/3;
        n=n/3+n%3;
    }
    printf("%d\n",s);
    return 0;
}

9. 壘骰子

10. 災後重建

Pear市一共有N(<=50000)個居民點,居民點之間有M(<=200000)條雙向道路相連。這些居民點兩兩之間都可以通過雙向道路到達。這種情況一直持續到最近,一次嚴重的地震毀壞了全部M條道路。
震後,Pear打算修復其中一些道路,修理第i條道路需要Pi的時間。不過,Pear並不打算讓全部的點連通,而是選擇一些標號特殊的點讓他們連通。
Pear有Q(<=50000)次詢問,每次詢問,他會選擇所有編號在[l,r]之間,並且 編號 mod K = C 的點,修理一些路使得它們連通。由於所有道路的修理可以同時開工,所以完成修理的時間取決於花費時間最長的一條路,即涉及到的道路中Pi的最大值。

你能幫助Pear計算出每次詢問時需要花費的最少時間麼?這裡詢問是獨立的,也就是上一個詢問裡的修理計劃並沒有付諸行動。

【輸入格式】
第一行三個正整數N、M、Q,含義如題面所述。
接下來M行,每行三個正整數Xi、Yi、Pi,表示一條連線Xi和Yi的雙向道路,修復需要Pi的時間。可能有自環,可能有重邊。1<=Pi<=1000000。
接下來Q行,每行四個正整數Li、Ri、Ki、Ci,表示這次詢問的點是[Li,Ri]區間中所有編號Mod Ki=Ci的點。保證參與詢問的點至少有兩個。

【輸出格式】
輸出Q行,每行一個正整數表示對應詢問的答案。

【樣例輸入】
7 10 4
1 3 10
2 6 9
4 1 5
3 7 4
3 6 9
1 5 8
2 7 4
3 2 10
1 7 6
7 6 9
1 7 1 0
1 7 3 1
2 5 1 0
3 7 2 1

【樣例輸出】
9
6
8
8

【資料範圍】
對於20%的資料,N,M,Q<=30
對於40%的資料,N,M,Q<=2000
對於100%的資料,N<=50000,M<=2*10^5,Q<=50000. Pi<=10^6.
Li,Ri,Ki均在[1,N]範圍內,Ci在[0,對應詢問的Ki)範圍內。

資源約定:
峰值記憶體消耗 < 256M
CPU消耗 < 5000ms

請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入…” 的多餘內容。
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include , 不能通過工程設定而省略常用標頭檔案。
提交時,注意選擇所期望的編譯器型別。

不會。。。看了好像挺靠譜的題解感覺要寫好久,而且不一定能寫對,所以就先不加這題的程式碼了。。。