山東科技大學第二屆ACM校賽解題報告

這次校賽的目的,是爲了省賽測試各種程序是否有問題。


熱身賽的逗比題有點打擊我,感覺正式賽應該不會出這種問題。開始的時候直接上了A題,然後大概是第六,前面好多友情隊,正式隊排名第二。

然後讀了讀B題,稍微想了一下,感覺不好搞,就去讀了一下C題,結果C題的正方形判斷只判斷了四個直角,沒有判四條邊長度相等,交了兩次 都是WA,然後想了一下 直接複製了一下上面的代碼 改了下AC了, 總排名大概是第4的位置,然後看到有人拿下了E題,就讀了一下E,結果發現是水題,就秒了。看了看榜,H又有人幹掉了,就一次A了H。

然後沒有榜,讀了K,A了K題。直接沒停下來。看到會做直接AC,AC的時候 已經被別人拿了FB。讀了讀 I,判斷IP,這個題不是做過麼,直接一次寫過了,原來做這個題的時候,題目寫不明白,坑死我了,交了好多次,名次一直在4-8之間,就進過一次第4。看了看F,試了試跑了一下循環,過了F。

這時候還有倆小時,然後到了第四小時,封榜了,也沒做出第8個,瑞神第一,我第二。

本來已經做不動了,看看哪個都不好辦,愁死了,還有人在一直期待我打敗瑞神,然後就一直幹D題,抱着打出來就能冠軍的想法,不小心推出了D,運氣吧,然後A掉了。這時候還有10分鐘,就不想寫了,考慮到瑞神可能也8題,很是糾結,因爲別人除非9題,要麼不可能超過我。心裏覺得10分鐘不會出題了,可還是想了10分鐘B題。當然還沒下手就到點了。

最後沒想到易神A了第八個,罰時比我多不少,導致在我後面,瑞神做的雖然快,但是沒A出第8個,就這樣混了第一,哦,這裏不得不說,剛剛讀了錕錕的解題報告,有些遺憾,

錕神受打擊,狀態不好就掛在了後面。


Problem A: 簡單計算

 

 

Description

給出n個十進制的數,找出這n個數的二進制表示中1的個數最少的數。

 

Input

輸入的第一行爲一個正整數T(1≤T≤20),代表測試數據組數。
對於每組測試數據,輸入的第一行爲一個正整數n(1≤n≤100000),第二行爲n個正整數A1、A2、…、An(1≤Ai≤10^9),每個數之間以空格分隔。

 

Output

每組數據輸出一行,先輸出數據組數,再輸出二進制中含1最少的數,如果存在多個數符合條件,輸出最小的那個。具體輸出格式見樣例輸出。

 

Sample Input

2 5 3 2 4 5 6 4 3 4 2 5

Sample Output

Case 1: 2
Case 2: 2



#include <iostream>
#include <limits.h>
#include <bitset>

using namespace std;

int main()
{
    int T, kase(0);
    cin >> T;
    while(T--){
        int n; cin >> n;
        int min1 = INT_MAX, minn = INT_MAX;
        for(int i = 0; i < n; ++i){
            int x;
            cin >> x;
            bitset<100> bit(x);
            if(bit.count() < min1 || (bit.count() == min1 && x < minn)){
                min1 = bit.count();
                minn = x;
            }
        }
        cout<<"Case "<< ++kase <<": "<< minn<<endl;
    }
    return 0;
}

<center><h2>Problem C: 正方形</h2><span class="green">Time Limit: </span>3 Sec  <span class="green">Memory Limit: </span>128 MB

</center><h2>Description</h2><div class="content"><p>在二維座標軸內給出四個點,這四個點能否構成一個正方形。</p><p></p></div><h2>Input</h2><div class="content"><p>第一行包括一個整數:T(1≤T≤30),表明有T組測試數據。
下面各行有8個整數:x1,y1,x2,y2,x3,y3,x4,y4(數據均在-1000,1000之間),以逆時針順序給出四個點的座標。</p><p></p></div><h2>Output</h2><div class="content"><p>對每個樣例,如果是正方形,則單獨在一行內輸出YES,否則,輸出NO。</p><p></p></div><h2>Sample Input</h2><div class="content"><span class="sampledata"></span><pre>2
0 0 1 0 1 1 0 1
-1 0 0 -2 1 0 2 0

Sample Output

YES
NO

HINT

Append Code

#include<iostream>
#define len(i) (p[(i+1)%4].x-p[i].x)*(p[(i+1)%4].x-p[i].x)+(p[(i+1)%4].y-p[i].y)*(p[(i+1)%4].y-p[i].y)
#define A(i)   (p[(i+1)%4].x-p[i].x)*(p[(i+2)%4].x-p[(i+1)%4].x)+(p[(i+1)%4].y-p[i].y)*(p[(i+2)%4].y-p[(i+1)%4].y)!=0
using namespace std;
typedef unsigned long long llu;
struct pp{
    int x,y;
};
int main(){
    int T,kase=0;
    cin>>T;
    while(T--){
        pp p[4];
        for(int i =0; i<4; i++) cin>>p[i].x>>p[i].y;
        bool failed(false);
        for(int i =0;i< 3; i++) if( len(i) !=len(i+1) ) failed=true;
        for(int i =0;i<=3; i++) if( A(i) ) failed=true;
        cout<<( failed? "NO":"YES")<<endl;
    }
    return 0;
}


<center><h2>Problem D: 切蛋糕</h2><span class="green">Time Limit: </span>3 Sec  <span class="green">Memory Limit: </span>128 MB

</center><h2>Description</h2><div class="content"><p>今年是ACM集訓隊成立五週年,這是一個值得祝福的事情。我們該送給ACM集訓隊一個怎樣的禮物呢?對於目前的大家來說,最好的禮物當然是省賽中的好成績,我不能參賽,就送給學校一個DOOM III球形大蛋糕吧,這可是名牌,估計要花掉我半年的銀子呢。切蛋糕的人,當然非吳教主莫屬。
等一等,喫蛋糕之前先考大家一個問題:如果吳教主在蛋糕上切了N刀(教主刀法極好,每一刀都是一個絕對的平面),最多可以把這個球形蛋糕切成幾塊呢?
做不出這個題目,沒有蛋糕喫的!</p><p></p></div><h2>Input</h2><div class="content"><p>第一行輸出一個T(T≤100),表示有T組。每組包含一個整數N(1≤N≤1000),表示切的刀數。</p><p></p></div><h2>Output</h2><div class="content"><p>對於每組輸入數據,請輸出對應的蛋糕塊數,每個測試實例輸出一行。</p><p></p></div><h2>Sample Input</h2><div class="content"><span class="sampledata"></span><pre>3
1
2
4

Sample Output

2
4
15

HINT

Append Code

推出遞推公式

 就很簡單了

<pre name="code" class="cpp">#include<iostream>
using namespace std;
int main(){
    int n,x;
    cin>>n;
    while(n--){
        cin>>x;
        cout<<(x*x*x+5*x+6)/6<<endl;
    }
    return 0;
}

Problem E: 畫笑臉
Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 37  Solved: 20
[Submit][Status][Web Board]
Description
用C語言畫些任意大小的笑臉來。畫法見Sample。


Input
T組數據,每組數據只有一個數N(1≤T≤20,1≤N≤20),表示笑臉的邊長大小。


Output
把笑臉畫出來吧。
注意:不要任何多餘的空格和空行,每兩組數據間輸出一個空行。


Sample Input
3
1
2
3

Sample Output
/\ /\
  _

 /\    /\
/  \  /  \

    __

  /\       /\
 /  \     /  \
/    \   /    \


      ___
HINT

Append Code

#include<iostream>
using namespace std;

void pri(int n){
    for(int i =0; i<n; i++) cout<<" ";
}
int main(){
    int T,n;
    cin>>T;
    while(T--){
        cin>>n;
        for(int i =1; i<=n; i++){
            pri(n-i);
            cout<<"/";
            pri(2*i-2);
            cout<<"\\";
            pri(n-i);
            pri(n);
            pri(n-i);
            cout<<"/";
            pri(2*i-2);
            cout<<"\\"<<endl;
        }
        for(int i =1;i<n;i++) cout<<endl;
        pri(2*n);
        for(int i =0;i<n;i++) cout<<"_";
        cout<<endl;
        if(T) cout<<endl;
    }
    return 0;
}

Problem F: 猜數字

Time Limit: 3 Sec  Memory Limit: 128 MB

Description

小X最近發明了一種新遊戲,他找來一堆卡片,每張卡片上都寫有一個四位數,然後由兩個人來玩。玩家A每次從這堆卡片中選擇一張,然後由玩家B告訴玩家A他猜的數字中有幾個與卡片中的相同,有幾個與卡片中的位置相同。

例如,玩家A抽到的卡片是1122。如果玩家A猜1234,因爲1,2這兩個數字同時存在於這兩個數中,而且1在這兩個數中的位置是相同的,所以玩家B會告訴玩家A猜對了2個數字,其中一個在正確的位置。如果玩家A猜1111,那麼玩家B會告訴他猜對2個數字,有2個在正確的位置。

現在給你一段遊戲過程,你的任務是根據這過程來判斷能否確定卡片上的四位數是什麼。

Input

輸入數據有多組。每組的第一行爲一個正整數N(1≤N≤100),表示共有N次遊戲過程。在接下來的N行中,每行三個整數x, y, z。玩家A猜這個四位數爲x,然後玩家B回答猜對了y個數字,其中z個在正確的位置上。當N=0時,輸入數據結束。

Output

每組輸入數據對應一行輸出。如果根據這段對話能確定這個四位數,則輸出”Yes”,若不能,則輸出"Not sure"。

Sample Input

6
4815 2 1
5716 1 0
7842 1 0
4901 0 0
8585 3 3
8555 3 2
2
4815 0 0
2999 3 3
0

Sample Output

Yes
Not sure

HINT

Append Code


#include<iostream>
#include<cstring>

using namespace std;

struct pp{
    int num,a,b;
    int d[4];
    pp(){}
    pp(int c) :num(c),a(0),b(0){
        for(int j =0;j<4;j++){
            d[j]=c%10;
            c/=10;
        }
    }
}p[110];

int main(){
    int n;

    while(cin>>n,n){
        for(int i =0;i<n;i++) {
            cin>>p[i].num>>p[i].a>>p[i].b;
            int temp=p[i].num;
            for(int j =0;j<4;j++){
                p[i].d[j]=temp%10;
                temp/=10;
            }
        }

        int have(0);
        for(int i =1000;i<10000;i++){
            int can(1);
            for(int j=0;j<n;j++){
                pp u(i);
                int n_a(0),n_b(0);
                for(int k=0;k<4; k++) if(u.d[k] ==p[j].d[k]) u.b++;
                if(u.b!=p[j].b) {can=0; break; }

                for(int k=0;k<4; k++){
                         if(u.d[0]==p[j].d[k]) {u.a++; u.d[0]=-1;}
                    else if(u.d[1]==p[j].d[k]) {u.a++; u.d[1]=-1;}
                    else if(u.d[2]==p[j].d[k]) {u.a++; u.d[2]=-1;}
                    else if(u.d[3]==p[j].d[k]) {u.a++; u.d[3]=-1;}
                }
                if(u.a!=p[j].a) {can=0; break; }
            }
            if(can){ have++;}
            if(have>2) break;
        }

        if(have==1) cout<<"Yes"<<endl;
        else cout<<"Not sure"<<endl;
    }
    return 0;
}




Problem H: 原創字符串

Time Limit: 3 Sec  Memory Limit: 128 MB

Description

我們稱一個字符串s爲“原創”當且僅當s不是N個字符串中的任意一個字符串的子串(子串:串中任意個連續字符組成的子序列)。現在有N個只包含小寫字母的字符串,你的任務是根據給出的N個字符串構造一個長度最小的“原創”字符串,如果存在多個長度最小的則輸出字典序最小的那個。

Input

對於每組測試數據,輸入的第一行爲一個正整數n(1≤n≤30)代表給定字符串的大小,接下來N行每行一個非空只包含小寫字母的字符串,每個字符串長度不超過20。
輸入以一行0結束。

Output

輸出符合要求的字符串,每組答案佔一行。

Sample Input

5
threehorses
goodsubstrings
secret
primematrix
beautifulyear
4
aa
bdefghijklmn
opqrstuvwxyz
c
0

Sample Output

j
ab

HINT

Append Code


#include<iostream>
#include<string>

using namespace std;
int out=0;
string s[35];
int n;

bool find(string s1,string s2){
    for(int i=0;i<s1.size()-s2.size()+1;i++){
        bool ok=0;
        if(s1[i]==s2[0]){
            ok=1;
            for(int j=1;j<s2.size();j++)
            if(s1[i+j]!=s2[j]) {ok=0; break;}
            if(ok) return 1;
        }
    }
    return 0;
}

void dfs(int v,int dig,int lem,string ss){
    ss[dig]=v;
    if(dig==lem-1){
        int ok=1;
        for(int i=0;i<n;i++){
            if(find(s[i],ss)) {ok=0; break;}
        }
        if(ok) { cout<<ss<<endl; out=1;}
    }
    else{
        for(int i =97; i<=122;i++)
            if(out==0) dfs(i,1,lem,ss);
            else break;
    }
    return;
}

int main(){
    while(cin>>n,n){
        out=0;
        for(int i =0;i<n;i++) cin>>s[i];

        for(int lem=1;;lem++){
            string ss(lem,0);
            for(int j=97;j<=122; j++)
                if(out==0) dfs(j,0,lem,ss);
                else break;
            if(out) break;
        }
    }
    return 0;
}

Problem I: IP地址

Time Limit: 1 Sec  Memory Limit: 32 MB
Submit: 2458  Solved: 54

Description

IP是英文Internet Protocol的縮寫,意思是“網絡之間互連的協議”,也就是爲計算機網絡相互連接進行通信而設計的協議。在因特網中,它是能使連接到網上的所有計算機網絡實現相互通信的一套規則,規定了計算機在因特網上進行通信時應當遵守的規則。任何廠家生產的計算機系統,只要遵守IP協議就可以與因特網互連互通。正是因爲有了IP協議,因特網才得以迅速發展成爲世界上最大的、開放的計算機通信網絡。因此,IP協議也可以叫做“因特網協議”。

互聯網協議地址(英語:Internet Protocol Address,又譯爲網際協議地址),縮寫爲IP地址(IP Address),在Internet上,一種給主機編址的方式。常見的IP地址,分爲IPv4與IPv6兩大類。

IP地址被用來給Internet上的電腦一個編號。大家日常見到的情況是每臺聯網的PC上都需要有IP地址,才能正常通信。我們可以把“個人電腦”比作“一臺電話”,那麼“IP地址”就相當於“電話號碼”,而Internet中的路由器,就相當於電信局的“程控式交換機”。

IP地址是一個32位的二進制數,通常被分割爲4個“8位二進制數”(也就是4個字節)。IP地址通常用“點分十進制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之間的十進制整數。例:點分十進IP地址(100.4.5.6),實際上是32位二進制數(01100100.00000100.00000101.00000110)。

現在,根據以下規則,編寫程序來判斷一個字符串是否是“點分十進制”表示的IP地址。

1 IP地址由四個整數跟三個'.'組成,就是“a.b.c.d”的形式。

2 a,b,c,d四個部分的數字位數都可以是1~3位,其整數值都在0~255之間。

3 不能有除了數字和'.'之外的字符出現。

Input

輸入有多行,每行是一個字符串s,s不超過100個字符。到文件尾結束。

Output

對於每個輸入,判斷串s是否爲合法的IP地址,如果正確輸出YES,否則NO。

Sample Input

192.168.100.16

Sample Output

YES

HINT

Append Code

#include<stdio.h>
#include<string.h>
#define N 105
int main()
{
    char a[N];
    while(gets(a)!=NULL)
    {
        int i,k=-1,wrong=0,sum,u=0;
        int n=strlen(a);
        for(i=0;i<=n;i++)
        {
            if(a[i]==46||a[i]==0)
            {
                sum=0,u++;
                if(i-k>4)
                    wrong=1;
                else
                {
                    for(k++;k<i;k++)
                       sum=sum*10+a[k]-48;
                    if(sum>255)
                        wrong=1;
                }
                k=i;
            }
            else if(a[i]>57||a[i]<48)
                wrong=1;
            if(a[i]==46&&(i==0||a[i-1]==46))
                wrong=1;
            if(wrong)
                goto end;
        }
    end:
        if(wrong||u!=4)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}

Problem K: 藏頭詩

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 39  Solved: 25
[Submit][Status][Web Board]

Description

ACM集訓隊有個小夥暗戀同班的姑娘,但是苦於害羞靦腆不敢直抒胸臆。於是小夥打算寫一首英文情詩給她。爲了使這首情詩高端霸氣上檔次,小夥經過三天三夜的精心創作寫了一首藏頭的情詩。請問你能看出他想要表達的真正內容嗎?

Input

輸入有T組(T≤20)。
每組數據第一行先輸入一個整數N(N<100),表示下面要輸入N行。
接下來N行,每行輸入一段英文(長度小於100,只含大小寫英文字母和空格)。

Output

每組輸出一行,爲藏頭詩要表達的真正內容。

Sample Input

1
8
I am a handsome man
lonely and long for you attention
of all the girls I met you gave me the deepest impression
Very lucky to know you
earn money to make you happy
you are the world
oh be ma side
u are the happiest person in the world

Sample Output

IloVeyou

HINT

Append Code

#include<iostream>
#include<vector>
#include<string>

using namespace std;

int main(){
    int T,kase=0;
    cin>>T;
    while(T--){
        int n;
        cin>>n;cin.get();
        vector<char> v;
        while(n--){
            string s;
            getline(cin,s);
            v.push_back(s[0]);
        }
        for(int i =0; i<v.size();i++) cout<<v[i];
        cout<<endl;
    }
    return 0;
}



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