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

 

posted @ 2020-06-12 14:37  lonely_wind  阅读(1294)  评论(0编辑  收藏  举报