2019天梯賽L1及L2全解


題目鏈接:https://pintia.cn/problem-sets/994805046380707840/problems/type/7?page=0

基礎級:L1-057~064

進階級:L2-029~032

登頂級:L3-022~024

題目說明:

前七題:水題,字符串,

估值一億的AI核心代碼(大模擬)

特立獨行的幸福(暴力模擬)                冰島人(暴力|LCA)

深入虎穴(最長路)                              彩虹瓶(水題-模擬)

 

emmmm,懷念當年我還是大一的時候啊,現在的我已經是個混吃等死的死宅了QAQ,總的來說當年這套題似乎也不是很難,我這種蒟蒻學了半年也能寫個110+的分數。。。想當時寫完我還自閉了好久,拖了隊伍的后退啊QAQ。。。

基礎級:

總的來說沒什么難的,當然除了最后一題。。。。最后一題調太久了而且最終還沒出來,要是當時直接扔了也不至於分數這么低,前面的七題大概半個小時就差不多了。

 PTA使我精神煥發(5)

沒什么好說的,直接printf就完事了

以下是AC代碼:

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

int main()
{
    printf ("PTA shi3 wo3 jing1 shen2 huan4 fa1 !\n");

    return 0;
}
View Code

 

6翻了(15)

沒什么好說的,就是不能用gets,那么只能換getline並用string來解決了,我們for一遍直接處理就好了

以下是AC代碼:

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

const int mac=1e3+10;

string s;

int main()
{
    getline(cin,s);
    int len=s.length();
    for (int i=0; i<len; i++){
        if (s[i]=='6'){
            int j,mis=0;
            for (j=i; j<len; j++){
                if (s[j]!='6') break;
                mis++;
            }
            i=j;
            if (mis<=3) 
                for (int k=1; k<=mis; k++) printf("6");
            else if (mis>3 && mis<=9) printf("9");
            else printf("27");
        }
        printf("%c",s[i]);
    }
    printf("\n");
    return 0;
}
View Code

 

敲笨鍾(20)

也沒什么好說的,讀一句處理一句就好了,至於怎么處理,直接暴力來就完事了,值得注意的一點是讀入整數過后要用getchar將回車吃掉,不然第一個字符串就是回車符了

以下是AC代碼:

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

string s;

int main()
{
    int n;
    scanf ("%d",&n);
    getchar();
    for (int i=1; i<=n; i++){
        getline(cin,s);
        int len=s.length()-1;
        int mid,mark=0;
        for (int j=0; j<=len; j++)
            if (s[j]==',') mid=j;
        if (s[mid-1]=='g' && s[mid-2]=='n' && s[mid-3]=='o')
            if (s[len-1]=='g' && s[len-2]=='n' && s[len-3]=='o'){
                mark=1;
                int pos,space=0;
                for (int j=len; j>mid; j--){
                    if (s[j]==' ') space++;
                    if (space==3) {pos=j;break;}
                }
                for (int j=0; j<=pos; j++) printf("%c",s[j]);
                printf("qiao ben zhong.\n");
            }
        if (!mark) printf("Skipped\n");
    }
    return 0;
}
View Code

 

心理陰影面積(5)

沒什么好說的,就是一個大三角形減去小三角形再減去一個梯形就完事了,值得注意的是這里的面積運算都要使用int型,最后的結果也是int型

以下是AC代碼:

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

int main()
{
    int x,y;
    int tot=100*100/2;
    scanf ("%d%d",&x,&y);
    int s1=(100-x)*(100-y)/2;
    int s2=(100+100-x)*y/2;
    printf("%d\n",tot-s1-s2);
    return 0;
}
View Code

 

新胖子公式(10)

emmmm,沒什么好說的了,不要加上精度誤差就能過

以下是AC代碼:

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

int main()
{
    double weight,heigt;
    cin>>weight>>heigt;
    double ans=(weight/(heigt*heigt));
    printf("%.1f\n",ans);
    if (ans>25) printf("PANG\n");
    else printf("Hai Xing\n");
    return 0;
}
View Code

 

幸運彩票(15)

這個也很簡單,直接看代碼

以下是AC代碼:

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

char s[10];

int solve(char c1,char c2,char c3)
{
    int p1=c1-'0',p2=c2-'0',p3=c3-'0';
    return p1+p2+p3;
}

int main()
{
    int n;
    scanf ("%d",&n);
    for (int i=1; i<=n; i++){
        scanf ("%s",s);
        int s1=solve(s[0],s[1],s[2]);
        int s2=solve(s[3],s[4],s[5]);
        if (s1==s2)
            printf("You are lucky!\n");
        else printf("Wish you good luck.\n");
    }
    return 0;
}
View Code

 

吃魚還是吃肉(10)

沒什么好說的,if-else判斷即可,復制粘貼別出錯就行了

以下是AC代碼:

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

int main()
{
    int n;
    scanf ("%d",&n);
    for (int i=1; i<=n; i++){
        int sx,height,weight;
        scanf ("%d%d%d",&sx,&height,&weight);
        if (sx==1){
            if (height>130) printf("ni li hai! ");
            else if (height==130) printf("wan mei! ");
            else printf("duo chi yu! ");

            if (weight>27) printf("shao chi rou!\n");
            else if (weight==27) printf("wan mei!\n");
            else printf("duo chi rou!\n");
        }
        else {
            if (height>129) printf("ni li hai! ");
            else if (height==129) printf("wan mei! ");
            else printf("duo chi yu! ");

            if (weight>25) printf("shao chi rou!\n");
            else if (weight==25) printf("wan mei!\n");
            else printf("duo chi rou!\n");
        }
    }
    return 0;
}
View Code

 

估值一億的AI核心代碼(20)

 emmmm,當時記得調了很久,現在看來。。。也不是很難,我們先做最簡單的替換,也就是將大寫變小寫(除了I),將“?”變成“!”,接下來我們必須先解決多余的空格問題,這個也不是很難,我們先搞定頭尾,這個就很簡單了,那么得出的新的頭尾設為head和tail。然后我們從head到tail直接for一遍一旦碰到非空格的我們就一直往下讀,遇到空格,我們要進行一個簡單的判斷,先往下讀,讀到非空格,判斷這個字符是不是數字和字母,(標點符號非常多,難以判斷),如果是的話我們就直接在新的字符串中添加一個空格,如果不是的話我們直接break:

string ss;
int head=0,tail=len-1;
while (s[head]==' ') head++;//空格消除
while (s[tail]==' ') tail--;
for (int i=head; i<=tail; i++) {
    int j;
    if (letter(s[i]) || number(s[i])) {
        for (j=i; j<=tail; j++) {
            if (!letter(s[j]) && !number(s[j])) break;
            ss+=s[j];
        }
        i=j-1;
    } 
    else if (s[i]==' ') {
        for (j=i; j<=tail; j++) {
            if (letter(s[j]) || number(s[j])) {
                ss+=' ';
                break;
            } 
            else if (s[j]!=' ') break;
        }
        i=j-1;
    } 
    else ss+=s[i];
}

這樣得到的ss就是一個比較完美的無多余空格的字符串,那么現在我們就只剩下替換I,me,can you,could you了,當然我們如果直接替換的話會有一定的難度,所以我們可以換一種方法思考,我們可以對要替換的單詞進行標記然后就沒了。標記過程如下:

int lens=ss.length();
for (int i=0; i<lens; i++) { //標記I,me,can you,could you的位置
    if (ss[i]=='I') {
        if (i==0 && !letter(ss[i+1]) && !number(ss[i+1])) id[i]=1;
        else if (ss[i-1]==' ' && !letter(ss[i+1]) && !number(ss[i+1]))
            id[i]=1;
    }

    else if (ss[i]=='m' && ss[i+1]=='e') {
        if (i==0 && !letter(ss[i+2]) && !number(ss[i+2])) id[i]=2;
        else if (ss[i-1]==' ' && !letter(ss[i+2]) && !number(ss[i+2]))
            id[i]=2;
    }

    else if (can(ss,i)) id[i]=3;
    else if (could(ss,i)) id[i]=4;
}

那么接下來就是編寫letter,number,can,could這4個判斷函數了

以下是AC代碼:

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

string s;
int id[1010];
//1--表示I,2--表示me,3表示can you,4表示could you
char cny[]={'c','a','n',' ','y','o','u'};
char cdy[]={'c','o','u','l','d',' ','y','o','u'};

int letter(char c)//判斷字母
{
    if (c>='a' && c<='z') return 1;
    if (c>='A' && c<='Z') return 1;
    return 0;
}

int number(char c)//判斷數字
{
    if (c>='0' && c<='9') return 1;
    return 0;
}

int can(string ss,int st)//判斷是否為獨立的can you
{
    if (st==0){
        for (int i=0; i<7; i++)
            if (ss[i+st]!=cny[i]) return 0;
        if (letter(ss[st+7]) || number(ss[st+7])) return 0;
    }
    else {
        if (ss[st-1]!=' ') return 0;
        for (int i=0; i<7; i++)
            if (ss[i+st]!=cny[i]) return 0;
        if (letter(ss[st+7]) || number(ss[st+7])) return 0;
    }
    return 1;
}

int could(string ss,int st)//判斷是否為獨立的could you
{
    if (st==0){
        for (int i=0; i<9; i++)
            if (ss[i+st]!=cdy[i]) return 0;
        if (letter(ss[st+9]) || number(ss[st+9])) return 0;
    }
    else {
        if (ss[st-1]!=' ') return 0;
        for (int i=0; i<9; i++)
            if (ss[i+st]!=cdy[i]) return 0;
        if (letter(ss[st+9]) || number(ss[st+9])) return 0;
    }
    return 1;
}

int main()
{
    int n;
    scanf ("%d",&n);
    getchar();
    while(n--){
        getline(cin,s);
        cout<<s<<endl;
        cout<<"AI: ";
        memset(id,0,sizeof id);
        int len=s.length();
        for (int i=0; i<len; i++){//簡單替換
            if (letter(s[i]))
                if (s[i]<'a' && s[i]!='I') s[i]+=32;
            if (s[i]=='?') s[i]='!';
        }
        string ss;
        int head=0,tail=len-1;
        while (s[head]==' ') head++;//空格消除
        while (s[tail]==' ') tail--;
        for (int i=head; i<=tail; i++){
            int j;
            if (letter(s[i]) || number(s[i])){
                for (j=i; j<=tail; j++){
                    if (!letter(s[j]) && !number(s[j])) break;
                    ss+=s[j];
                }
                i=j-1;
            }
            else if (s[i]==' '){
                for (j=i; j<=tail; j++){
                    if (letter(s[j]) || number(s[j])) {ss+=' '; break;}
                    else if (s[j]!=' ') break;
                }
                i=j-1;
            }
            else ss+=s[i];
        }
        //得到的ss無多余空格

        int lens=ss.length();
        for (int i=0; i<lens; i++){//標記I,me,can you,could you的位置
            if (ss[i]=='I'){
                if (i==0 && !letter(ss[i+1]) && !number(ss[i+1])) id[i]=1;
                else if (ss[i-1]==' ' && !letter(ss[i+1]) && !number(ss[i+1]))
                    id[i]=1;
            }

            else if (ss[i]=='m' && ss[i+1]=='e'){
                if (i==0 && !letter(ss[i+2]) && !number(ss[i+2])) id[i]=2;
                else if (ss[i-1]==' ' && !letter(ss[i+2]) && !number(ss[i+2])) 
                    id[i]=2;
            }

            else if (can(ss,i)) id[i]=3;
            else if (could(ss,i)) id[i]=4;
        }
        for (int i=0; i<lens; i++){
            if (!id[i]) cout<<ss[i];
            else if (id[i]==1) cout<<"you";
            else if (id[i]==2) {cout<<"you"; i++;}
            else if (id[i]==3) {
                cout<<"I can";
                i+=6;
            }
            else if (id[i]==4){
                cout<<"I could";
                i+=8;
            }
        }
        cout<<endl;
    }
    return 0;
}
View Code

 

進階級:

emmm,也基本都是水題,除了冰島人有點惡心人。。。我想當初我要是扔掉大模擬那題那得加多少分啊QAQ!!!

特立獨行的幸福(25)

emmm,乍一看還有點蒙,不過按照他的要求來的話也不是很難,就是感覺有點難的樣子。。。。我們直接暴力就可以了,在區間內尋找,然后在尋找的過程中進行標記,對於已經標記過的點就直接扔了,也是挺簡單的一題

以下是AC代碼:

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

const int mac=1e4+10;

int prim[mac],vis[mac],num[mac];
bool mk[mac];

int solve(int m)
{
    int tot=0;
    while (m){
        int p=m%10;
        tot+=p*p;
        m/=10;
    }
    return tot;
}

int ok(int s,int m)
{
    memset(mk,false,sizeof mk);
    mk[m]=true;
    while (m!=1){
        m=solve(m);
        if (mk[m]) return -1;
        mk[m]=true;vis[m]=1;
        s++;
    }
    return s-1;
}

int main()
{
    int l,r;
    int p=sqrt(mac);
    for (int i=2; i<=p; i++)
        if (!prim[i])
            for (int j=i*i; j<=mac; j+=i) prim[j]=1;
    scanf ("%d%d",&l,&r);
    for (int i=l; i<=r; i++){
        if (vis[i]) continue;
        num[i]=ok(1,i);
    }
    int yes=0;
    for (int i=l; i<=r; i++){
        if (vis[i]) continue;
        if (num[i]<1) continue;
        if (!prim[i]) yes=1,printf ("%d %d\n",i,num[i]*2);
        else yes=1,printf ("%d %d\n",i,num[i]);
    }
    if (!yes) printf ("SAD\n");
    return 0;
}
View Code

 

冰島人(25)

首先,看題目。。。。真的看了很久。。。看不懂QAQ,所謂的其他人不知道指的是什么,題目說保證維京人的起源都是男性m,那么f是個什么鬼?直接當場去世。。。。所謂的五代以內也有點疑惑

 好吧,題目還是要做的。。。。硬着頭皮肝了一下,既然說起源都是男性m,那么f應該沒什么用了吧,扔掉后跑了一遍。。。19分,加上f,把她當祖宗另加一個if-else判斷末尾。。。23分,原來過了測試點的沒過,我。。。。

然后我就想了想,只改變性別試試,至於她的姓可以和m的一樣,這樣就可以最大限度地保持原來代碼的模樣,結果一下子就過了。。。。真是蜜汁WA

不過本題的數據感覺有點水。。。本來想用LCA的,結果直接暴力都可以過,這里先將其中一個點的所有父親都找出來,並打上標記,附上到每個點的距離。然后跑另一個點就完事了。

以下是AC代碼:

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

const int mac=1e5+10;

struct node
{
    string ming,xing;
    int sx;//0女,1男
}name[mac];
int fa[mac];
unordered_map<string,int>q1,q2;

int same(string s1,string s2,int id1,int id2)
{
    unordered_map<int,int>dis,vis;
    dis[id1]=1;vis[id1]=1;
    int p=1;
    while(fa[id1]!=-1){
        id1=fa[id1];
        dis[id1]=++p;
        vis[id1]=1;
        if (id1==id2) return 0;
    }
    p=1;
    while (fa[id2]!=-1){
        id2=fa[id2];
        ++p;
        if (vis[id2]){
            if (dis[id2]>4 && p>4) return 1;
            else return 0;
        }
    }
    return 1;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    memset(fa,-1,sizeof fa);
    for (int i=1; i<=n; i++){
        string s1,s2;
        cin>>s1>>s2;
        q1[s1]=i;
        int len2=s2.length();
        if (s2[len2-1]=='n'){
            name[i].sx=1;
            name[i].ming=s1;
            name[i].xing=s2.substr(0,len2-4);
        }
        else if (s2[len2-1]=='r'){
            name[i].sx=0;
            name[i].ming=s1;
            name[i].xing=s2.substr(0,len2-7);
        }
        else {
            name[i].ming=s1;
            if (s2[len2-1]=='m') name[i].sx=1;
            else name[i].sx=0;
            name[i].xing="m";
        }
    }
    for (int i=1; i<=n; i++){
        if (name[i].xing=="m") continue;
        fa[i]=q1[name[i].xing];
        if (!fa[i]) fa[i]=-1;
    }
    int m;
    cin>>m;
    while (m--){
        string ming1,xing1,ming2,xing2;
        cin>>ming1>>xing1>>ming2>>xing2;
        if (!q1[ming1] || !q1[ming2]){
            cout<<"NA"<<endl;
            continue;
        }
        if (name[q1[ming1]].sx==name[q1[ming2]].sx){
            cout<<"Whatever"<<endl;
            continue;
        }
        if (same(ming1,ming2,q1[ming1],q1[ming2])){
            cout<<"Yes"<<endl;
            continue;
        }
        cout<<"No"<<endl;
    }
    return 0;
}
View Code

 

深入虎穴(25)

emmmm,看起來不是很難,確實也不是很難,就是坑了點,首先就是入口不知道(我剛開始一直以為是1)QAQ,實際上是沒有入度的點,接下來就是他有一個n=1的數據。。。。那么最短距離就是0。。。我在這兩個地方栽了一回。實際上就是跑個dij改編的最長路就完事了。

以下是AC代碼:

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

const int mac=1e5+10;
struct node
{
    int to,w,next;
}eg[mac<<2];
struct way
{
    int id,s;
    bool operator <(const way&a)const{
        return s<a.s;
    }
};
int head[mac],num=0,dis[mac],vis[mac],n;
int fa[mac];

void add(int u,int v)
{
    eg[++num]=node{v,1,head[u]};
    head[u]=num;
}

void dij(int id)
{
    priority_queue<way>q;
    q.push(way{id,0});
    while (!q.empty()){
        way now=q.top();
        q.pop();
        int u=now.id;
        for (int i=head[u]; i!=-1; i=eg[i].next){
            int v=eg[i].to;
            if (dis[u]+eg[i].w>dis[v]) {
                dis[v]=dis[u]+eg[i].w;
                q.push(way{v,dis[v]});
            }
        }
    }
    int mx=-1,mxid;
    for (int i=1; i<=n; i++)
        if (dis[i]>mx) mx=dis[i],mxid=i;
    printf("%d\n",mxid);
}

int main()
{
    scanf ("%d",&n);
    memset(head,-1,sizeof head);
    for (int i=1; i<=n; i++){
        int m;
        scanf ("%d",&m);
        for (int j=1; j<=m; j++){
            int v;
            scanf ("%d",&v);
            fa[v]=i;
            add(i,v);
        }
    }
    for (int i=1; i<=n; i++) 
        if (!fa[i]){
            dij(i);break;
        }
    return 0;
}
View Code

 

彩虹瓶(25)

 emmm,像這種沒有罰時的情況下我們可以寫個隨機數去多跑幾遍,至於得幾分那就看命了QAQ

先看題目。。。。有點長,看完之后覺得。。。太簡單了!寫一發。。。。確實簡單,用個簡單的棧模擬一下過程跑一跑就完事了

以下是AC代碼:

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

int id[1010],sstack[1010];

int main()
{
    int n,m,s;
    scanf ("%d%d%d",&n,&m,&s);
    while (s--){
        for (int i=1; i<=n; i++)
            scanf ("%d",&id[i]);
        int tail=0,use=1,mark=0;
        for (int i=1; i<=n; i++){
            if (id[i]==use) use++;
            else {
                while (tail && sstack[tail-1]==use) {use++; tail--;}
                if (id[i]==use) {use++; continue;}
                sstack[tail++]=id[i];
                if (tail>m) {mark=1; printf("NO\n"); break;}
            }
        }
        while (tail && sstack[tail-1]==use) {use++; tail--;}
        if (!mark & !tail) printf("YES\n");
        else if (!mark) printf("NO\n");
    }
    return 0;
}
View Code

 

登頂級:

emmm。。。。有點懶了,下次一定記得補

地鐵一日游

計算圖

Oriol和David

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM