2020.10.17-pta天梯练习赛补题
阅读原文时间:2023年07月08日阅读:4

7-5敲笨钟

微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。为了增加敲钟的趣味性,还会糟改几句古诗词。其糟改的方法为:去网上搜寻压“ong”韵的古诗词,把句尾的三个字换成“敲笨钟”。例如唐代诗人李贺有名句曰:“寻章摘句老雕虫,晓月当帘挂玉弓”,其中“虫”(chong)和“弓”(gong)都压了“ong”韵。于是这句诗就被糟改为“寻章摘句老雕虫,晓月当帘敲笨钟”。

现在给你一大堆古诗词句,要求你写个程序自动将压“ong”韵的句子糟改成“敲笨钟”。

输入格式:

输入首先在第一行给出一个不超过 20 的正整数 N。随后 N 行,每行用汉语拼音给出一句古诗词,分上下两半句,用逗号 , 分隔,句号 . 结尾。相邻两字的拼音之间用一个空格分隔。题目保证每个字的拼音不超过 6 个字符,每行字符的总长度不超过 100,并且下半句诗至少有 3 个字。

输出格式:

对每一行诗句,判断其是否压“ong”韵。即上下两句末尾的字都是“ong”结尾。如果是压此韵的,就按题面方法糟改之后输出,输出格式同输入;否则输出 Skipped,即跳过此句。

输入样例:

5
xun zhang zhai ju lao diao chong, xiao yue dang lian gua yu gong.
tian sheng wo cai bi you yong, qian jin san jin huan fu lai.
xue zhui rou zhi leng wei rong, an xiao chen jing shu wei long.
zuo ye xing chen zuo ye feng, hua lou xi pan gui tang dong.
ren xian gui hua luo, ye jing chun shan kong.

输出样例:

xun zhang zhai ju lao diao chong, xiao yue dang lian qiao ben zhong.
Skipped
xue zhui rou zhi leng wei rong, an xiao chen jing qiao ben zhong.
Skipped
Skipped题解:先判断上下两句是否以“ong”结尾,直接判断或者用substr()截取判断都行,若都押韵则从最后往前数三个空格,空格及空格前的直接输出,后面直接输出“qiao ben zhong.”

#include
#include
#include
#include
using namespace std;
/*int f(string str)//用不用这个都可以过
{
if(str=="ong")return 1;
else return 0;
}*/
int main()
{
int n;
cin>>n;
//getchar();
char ch=getchar();//用于接收换行符,防止影响下面字符串的输入
string s,b,d;
while(n--)
{

    getline(cin,s);

    long long m=s.size();  
    long long k=0,q=0;  
    for(long long i=0;i<m;i++)  
    {  
        if(s\[i\]==','&&i-3>=0)//\*\*条件要全,尤其后面这句\*\*,不然运行超时  
        {  
            b=s.substr(i-3,3);//截取三个字符  
            if(b=="ong")  
            {  
                k=1;  
            }  
            else  
            {  
                k=0;  
                break;  
            }  
        }  
        if(k==1&&s\[i\]=='.'&&i-3>=0)//条件\*\*  
        {  
            d=s.substr(i-3,3);//截取字符  
            if(d=="ong")q=1;  
            else  
            {  
                q=0;  
                break;  
            }  
        }  
    }  
    if(q==1&&k==1)  
    {  
        long long ct=0,r;  
       for( r=m-1;r>=0;r--)  
       {  
           if(s\[r\]==' ')++ct;//从后往前找到三个空格即可,空格及空格前的直接输出  
           if(ct==3)  
           {  
               break;  
           }  
       }  
       for(long long i=0;i<=r;i++)  
        {  
            cout<<s\[i\];

        }  
        cout<<"qiao ben zhong."<<endl;//最后输出“敲笨钟。”  
    }  
    else if(k==0||q==0) cout<<"Skipped"<<endl;  
}  

}

7-4

出生年

以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才遇到4个数字都不相同的年份。”也就是说,直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求,自动填充“我出生于y年,直到x岁才遇到n个数字都不相同的年份”这句话。

输入格式:

输入在一行中给出出生年份y和目标年份中不同数字的个数n,其中y在[1, 3000]之间,n可以是2、或3、或4。注意不足4位的年份要在前面补零,例如公元1年被认为是0001年,有2个不同的数字0和1。

输出格式:

根据输入,输出x和能达到要求的年份。数字间以1个空格分隔,行首尾不得有多余空格。年份要按4位输出。注意:所谓“n个数字都不相同”是指不同的数字正好是n个。如“2013”被视为满足“4位数字都不同”的条件,但不被视为满足2位或3位数字不同的条件。

输入样例1:

1988 4

输出样例1:

25 2013

输入样例2:

1 2

输出样例2:

0 0001

#include
using namespace std;
int main()
{
int y,n,ct,b[10000];
cin>>y>>n;

//cout<<b\[0\]<<endl;  
for(int i=0; ;i++)  
{  
    memset(b,0,sizeof(b));  
    ct=0;  
    int yy=y+i;  
    b\[yy/1000\]=1;  
    //cout<<b\[yy/1000\]<<"\*"<<endl;  
    b\[yy/100%10\]=1;  
    //cout<<b\[yy/100%10\]<<endl;  
    b\[yy/10%10\]=1;  
    //cout<<b\[yy/10%10\]<<endl;  
    b\[yy%10\]=1;  
    //cout<<b\[yy%10\]<<"\*"<<endl;  
    for(int j=0;j<=9;j++)  
    {  
        if(b\[j\]==1)ct++;  
    }  
    if(ct==n)  
    {

        cout<<i<<" ";  
        printf("%04d\\n",yy);  
        break;  
    }  
}  

}

7-10抢红包

没有人没抢过红包吧…… 这里给出N个人之间互相发红包、抢红包的记录,请你统计一下他们抢红包的收获。

输入格式:

输入第一行给出一个正整数N(≤),即参与发红包和抢红包的总人数,则这些人从1到N编号。随后N行,第i行给出编号为i的人发红包的记录,格式如下:

N​1​​

其中K(0)是发出去的红包个数,N​i​​是抢到红包的人的编号,P​i​​(>)是其抢到的红包金额(以分为单位)。注意:对于同一个人发出的红包,每人最多只能抢1次,不能重复抢。

输出格式:

按照收入金额从高到低的递减顺序输出每个人的编号和收入金额(以元为单位,输出小数点后2位)。每个人的信息占一行,两数字间有1个空格。如果收入金额有并列,则按抢到红包的个数递减输出;如果还有并列,则按个人编号递增输出。

输入样例:

10
3 2 22 10 58 8 125
5 1 345 3 211 5 233 7 13 8 101
1 7 8800
2 1 1000 2 1000
2 4 250 10 320
6 5 11 9 22 8 33 7 44 10 55 4 2
1 3 8800
2 1 23 2 123
1 8 250
4 2 121 4 516 7 112 9 10

输出样例:

1 11.63
2 3.63
8 3.63
3 2.11
7 1.69
6 -1.67
9 -2.18
10 -3.26
5 -3.26
4 -12.32

#include
using namespace std;
struct Student
{
int num;//编号
float sum=0.00;//金额
long long ct=0;//个数
};
bool cmp(Student k,Student p)
{
if(k.sum!=p.sum)return k.sum>p.sum;
if (k.sum==p.sum&&k.ct!=p.ct)return k.ct>p.ct;
else {
return k.num>n;
Student s[n+10];
for(int i=1;i<=n;i++) { int a; s[i].num=i;//**/ cin>>a;
for(int j=0;j>k>>p;//编号及金额

        s\[i\].sum-=p;  
        s\[k\].num=k;  
        s\[k\].sum+=p;  
        s\[k\].ct++;  
    }  
}  
sort(s+1,s+n+1,cmp);  
for(int i=1;i<=n;i++)  
{  
    printf("%d %.2lf\\n",s\[i\].num,s\[i\].sum\*1.000/100);  
}

}

7-7A-B

本题要求你计算A−B。不过麻烦的是,A和B都是字符串 —— 即从字符串A中把字符串B所包含的字符全删掉,剩下的字符组成的就是字符串A−B。

输入格式:

输入在2行中先后给出字符串A和B。两字符串的长度都不超过1,并且保证每个字符串都是由可见的ASCII码和空白字符组成,最后以换行符结束。

输出格式:

在一行中打印出A−B的结果字符串。

输入样例:

I love GPLT!  It's a fun game!
aeiou

输出样例:

I lv GPLT!  It's  fn gm!

#include
using namespace std;
#define speed_up ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int main()
{
string s,b;
getline(cin,s);
getline(cin,b);//**/
int m=s.size();
int n=b.size();
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(s[i]==b[j])
{
s[i]='0';
}
}
}
for(int i=0;i<m;i++)
{
if(s[i]!='0')cout<<s[i];
}
cout<<endl;
}

7-11互评成绩

学生互评作业的简单规则是这样定的:每个人的作业会被k个同学评审,得到k个成绩。系统需要去掉一个最高分和一个最低分,将剩下的分数取平均,就得到这个学生的最后成绩。本题就要求你编写这个互评系统的算分模块。

输入格式:

输入第一行给出3个正整数N(3 < N ≤,学生总数)、k(3 ≤ k ≤ 10,每份作业的评审数)、M(≤ 20,需要输出的学生数)。随后N行,每行给出一份作业得到的k个评审成绩(在区间[0, 100]内),其间以空格分隔。

输出格式:

按非递减顺序输出最后得分最高的M个成绩,保留小数点后3位。分数间有1个空格,行首尾不得有多余空格。

输入样例:

6 5 3
88 90 85 99 60
67 60 80 76 70
90 93 96 99 99
78 65 77 70 72
88 88 88 88 88
55 55 55 55 55

输出样例:

87.667 88.000 96.000

#include
using namespace std;
int main()
{
int n,k,m,i,j=1;
cin>>n>>k>>m;

double b\[10100\],sum=0,a\[10100\];  

while(n--){
sum=0;
double maxn=-1,minn=110;
for(i=1;i<=k;i++) { cin>>a[i];
sum+=a[i];
maxn=max(maxn,a[i]);
minn=min(minn,a[i]);

}  
//cout<<maxn<<"\*\*\*"<<minn<<endl;  
sum-=maxn;  
sum-=minn;  
b\[j\]=sum\*1.00/(k-2);//求出每行的平均数  

//cout<<b[j]<<endl;
j++;
}
sort(b,b+j+1);
for(i=j-m+1;i<=j;i++)//输出得分最高的m个值
{
if(i!=j)
printf("%.3lf ",b[i]);
else printf("%.3lf",b[i]);
}
}

7-9小字辈

本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。

输入格式:

输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。一行中的数字间以空格分隔。

输出格式:

首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。

输入样例:

9
2 6 5 5 -1 5 6 4 7

输出样例:

4
1 9

 题解:找到序号和辈分直接的对应关系,用递归来构建(1.不全对有错样例倒是过了2.来自大佬的代码)

1.

#include
using namespace std;
int pre[100010],range[100010];
int f(int i)
{
if(pre[i]==-1)
{
range[i]=1;
return 1;
}
if(range[pre[i]]>0)
{
range[i]=range[pre[i]]+1;
return range[i];
}
else {
range[i]=f(pre[i])+1;
return range[i];
}
}
int main()
{
int n;
cin>>n;
int s[n+5],i,j,ct=0;
for(i=1;i<=n;i++) { pre[i]=i; } for(i=1;i<=n;i++) { cin>>s[i];
pre[i]=s[i];
}
for(i=1;i<=n;i++)
{
f(i);
ct=max(ct,range[i]);
}
cout<<ct<<endl;
int num=0;
for(i=1;i<=n;i++)
{
if(ct==range[i]&&!num)
{
cout<<i;
num++;
}
else if(ct==range[i]&&num==1)
{
cout<<" "<<i;
num++;
}
}
}

2.

#include
#define MAX_N 100009
int s[MAX_N] ,layer[MAX_N] = {0};

int find_layer(int k) {
// 如果layer[k]非0就说明已经知道了辈分,直接返回
if (layer[k]) return layer[k];
// 不知道的话就通过上一代的数据来计算
layer[k] = find_layer(s[k]) + 1;
return layer[k];
}

int main(){
int n, x;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) { scanf("%d", &s[i]); if (s[i] == -1){ // 直接记录辈分最大的成员序号 x = i; layer[i] = 1; } } // 找到最大的代数,同时也调用find_layer函数来构建表 int max = 0; for (int j = 1; j <= n; ++j) { int tmp = find_layer(j); if (tmp > max) max = tmp;
}
int flag = 1; // 解决一下末尾不包含空格的问题
printf("%d\n", max);
for (int i = 1; i <= n; ++i) {
if (layer[i] == max){
if (flag) flag = 0;
else printf(" ");
printf("%d", i);
}
}
}

7-12深入虎穴

著名的王牌间谍 007 需要执行一次任务,获取敌方的机密情报。已知情报藏在一个地下迷宫里,迷宫只有一个入口,里面有很多条通路,每条路通向一扇门。每一扇门背后或者是一个房间,或者又有很多条路,同样是每条路通向一扇门…… 他的手里有一张表格,是其他间谍帮他收集到的情报,他们记下了每扇门的编号,以及这扇门背后的每一条通路所到达的门的编号。007 发现不存在两条路通向同一扇门。

内线告诉他,情报就藏在迷宫的最深处。但是这个迷宫太大了,他需要你的帮助 —— 请编程帮他找出距离入口最远的那扇门。

输入格式:

输入首先在一行中给出正整数 N(<),是门的数量。最后 N 行,第 i 行(1)按以下格式描述编号为 i 的那扇门背后能通向的门:

K D[1] D[2] ... D[K]

其中 K 是通道的数量,其后是每扇门的编号。

输出格式:

在一行中输出距离入口最远的那扇门的编号。题目保证这样的结果是唯一的。

输入样例:

13
3 2 3 4
2 5 6
1 7
1 8
1 9
0
2 11 10
1 13
0
0
1 12
0
0

输出样例:

12

题解:用数组来模拟邻接表来建图,然后这题的入口需要找到入度为0的那个门,在输入的时候可以先将有路到达的门先标记,然后遍历一下找到没有标记的那个门就找到入口了,然后在广搜找到最远的那个门&nbsp;

没太懂该题,以下来自大佬
#include
#include
#include
#include
using namespace std;
struct haha
{
int num;
int next;
};
int head[100009],tail[100009],flag[100009],len[100009],t=1;
int maxlen=-1,maxflag;
struct haha p[200000];
queue dui;
void add(int t1,int t2)
{
if(head[t1]==0)
{
head[t1]=t;
tail[t1]=t;
t++;
}
p[tail[t1]].next=t;
p[t].num=t2;
tail[t1]=t;
t++;
}
void bfs()
{
while(!dui.empty())
{
int u=dui.front();
if(head[u]!=0)
{
int i=p[head[u]].next;
while(i!=0)
{
dui.push(p[i].num);
len[p[i].num]=len[u]+1;
i=p[i].next;
}
}
else
{
if(len[u]>maxlen)
{
maxlen=len[u];
maxflag=u;
}
}
dui.pop();
}
}
int main(int argc, char *argv[]) {
int a,t1,t2;
scanf("%d",&a);
for(int n=1;n<=a;n++)
{
scanf("%d",&t1);
for(int m=0;m<t1;m++)
{
scanf("%d",&t2);
add(n,t2);
flag[t2]++;
}
}
int n;
for(n=1;n<=a;n++)
{
if(flag[n]==0)
{
break;
}
}
dui.push(n);
bfs();
printf("%d",maxflag);
return 0;

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章