22级天梯赛题解
基础题
1-1 无所谓,我会出手
请直接输出 :“It doesn’t matter,I’ll do it.”(输出不含引号)。
- 直接输出即可。
int main() { printf("It doesn't matter,I'll do it."); return 0; }
1-2 数组总和
给出一个正整数 n 和一段长度为n的数组a1,a2…an ,请输出1×a1+2×a2+3×a3+4×a 4+…+n×an的结果。
输入格式
第一行为 整数 n(1<=n<=1e3)
第二行为n 个整数 ai(1<=ai<=1e9)
输出格式
输出一行一个正整数,代表题目要求的值。
样例输入
4
1 2 3 4
样例输出
30
- 使用for循环,初始化i=1,每次相乘后储存到sum里。注意sum需要long long类型,避免爆int。
int main() { int n,i; long long sum=0,x; scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%lld",&x); sum+=x*i; } printf("%lld",sum); return 0; }
1-3 捡到一个矩形
这天,我捡到了一个二维坐标轴,坐标轴上有一个矩形,现在给出一个点的坐标,问这个坐标是否在矩形中。
输入格式
输入第一行一个整数t,代表测试组数 (1<=t<=10)
接下来2×t行,每组测试用例第一行为四个整数,分别为正方形的左下角的坐标x1,y1和矩形的右上角 x2,y2
第二行为询问的点的坐标 x,y(−1e9<=x,y,x1,x2,y1,y2<=1e9)
输出格式
如果在矩形中或者在矩形的边界上,输出 YES;否则输出 NO。
样例输入
2
0 0 2 2
1 1
1 1 2 2
0 0
样例输出
YES
NO
- 坐标在给出的范围之内即可。
int main() { int n,i,x1,x2,y1,y2,x,y; scanf("%d",&n); for(i=0;i<n;i++){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); scanf("%d%d",&x,&y); if(x>=x1&&x<=x2&&y>=y1&&y<=y2) printf("YES\n"); else printf("NO\n"); } return 0; }
1-4 字符转换
现给你一种对字符的操作,使其变成该字符在字母表后的第x个位置,x为该字符在字母表中的位置。例如,对字符a进行操作,会将其变成a后的第一个字母,即b;对字符b进行操作,会将其变成b后的第二个字母,即d….以此类推。需要注意的是,该字母表是一个循环字母表,即字符z后的第一个字符是a,a后又是b,循环往复。现在给你一个字符串s,s 均由小写字母组成,1<=∣s∣<=1e5,请输出对字符串s的每一位字符进行操作后的结果。
输入格式
一行输入一个字符串s,含义如题面所示
输出格式
输出一行一个字符串,代表对s每一位字符进行操作后的结果。
样例输入
upupup
样例输出
pfpfpf
- 难点是对循环的处理,我的处理方法是通过判断26个字母的中间作为是否循环的标志
int main() { char arr[100005]; scanf("%s",arr); for(int i=0;arr[i]!='\0';i++){ if(arr[i]-'a'+1>13) arr[i]-=25-arr[i]+'a'; //等同于26-(arr[i]-'a'+1) else arr[i]+=arr[i]-'a'+1; } for(int i=0;arr[i]!='\0';i++){ printf("%c",arr[i]); } return 0; }
1-5 捡到了一个成绩
天梯赛过后,所有同学的成绩被打印在一张纸上。现在老师想要统计某班得分的均值,以及得分高于这个均值的同学们的分数之和,请你帮助老师计算出这两个值。
输入格式
第一行输入一个正整数n,代表该班级的人数。(1<=n<=30)
第二行输入n个整数,代表第i名同学的得分x。(0<=x<=290)
输出格式
输出两行,第一行输出一个实数,代表得分的均值。(保留到小数点后三位)
第二行输出一个整数,代表得分高于该班级分数均值的同学们的分数之和。
样例输入
6
13 105 237 173 273 134
样例输出
155.833
683
- 简单题,注意整型要*1.0
int main() { int n,sum=0,sum2=0,arr[10000]; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&arr[i]); sum+=arr[i]; } double aver=sum*1.0/n; for(int i=0;i<n;i++){ if(arr[i]*1.0>aver) sum2+=arr[i]; } printf("%.3lf\n%d",aver,sum2); return 0; }
1-6 炎爆
cys学姐非常喜欢Arknights这款游戏,而其中伊芙利特是她最引以为傲的干员之一。给你一个n×n的矩形a,矩形中的每一个位置都有一个敌人,其中a[x][y]代表矩形第x行,第y列上的敌人。假设伊芙利特部署在(x,y)的位置上,并且朝向右,那么伊芙利特会对(x,y),(x,y+1),(x,y+2)….(x,n)的所有敌人造成1点伤害。现在给你q次部署,每次部署都给出一个部署位置(x,y),代表伊芙利特部署在矩形的第x行,第y列,再给出一个字符op,代表伊芙利特的朝向(U代表向上,R代表向右,D代表向下,L代表向左)。你能精确算出每个敌人受到的伤害吗?
输入格式
第一行一个正整数n,代表矩形的大小(1<=n<=100),初始情况下所有敌人受到的伤害为0。
第二行给出一个正整数q,代表伊芙利特的部署次数(1<=q<=50)。
接下来q行,每行给定一个数对(x,y),1<=x,y<=n,代表伊芙利特的部署位置,和一个字符op,op∈{U,R,D,L},代表伊芙利特的朝向。
输出格式
输出n行,每行n个整数,分别对应矩阵a中每个敌人受到的伤害。
样例输入
5
3
2 2 R
4 3 U
5 5 L
样例输出
0 0 1 0 0
0 1 2 1 1
0 0 1 0 0
0 0 1 0 0
1 1 1 1 1
- 使用for循环控制好变量处理即可,不难但有点麻烦。
注意行末空格的处理!int main() { int n,x,numx,numy; char dire; scanf("%d",&n); int arr[n+1][n+1]; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ arr[i][j]=0; } } scanf("%d",&x); for(int i=0;i<x;i++){ scanf("%d%d %c",&numx,&numy,&dire); if(dire=='U'){ for(int z=0,j=0;j<numx;j++,z++){ arr[numx-1-z][numy-1]++; } } else if(dire=='R'){ for(int z=0,j=0;j<n-numy+1;j++,z++){ arr[numx-1][numy-1+z]++; } } else if(dire=='D'){ for(int z=0,j=0;j<n-numx+1;j++,z++){ arr[numx-1+z][numy-1]++; } } else if(dire=='L'){ for(int z=0,j=0;j<numy;j++,z++){ arr[numx-1][numy-1-z]++; } } } for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(j==0) printf("%d",arr[i][j]); else printf(" %d",arr[i][j]); if(j==n-1) printf("\n"); } } return 0; }
1-7 攻略迷宫
小A准备挑战一个副本,他的角色拥有 x 点生命值,boss 每第 y 秒攻击一次,每次对角色造成1点伤害,当角色生命值为零时游戏结束,不会再受到攻击。现在给你一个时间段,假如小A从这个时间段开始时着手攻略副本,小A想知道他的角色在这段时间内会承受多少次攻击,以及最后一次被攻击的时间。
输入格式
第一行两个整数 x 和 y(1<=x,y<=100) ,由空格隔开。
下面两行两个时间,格式为XX:XX:XX ,代表给定的时间段的开始和结束时间。
数据保证时间合法,且开始时间和结束时间在同一天
输出格式
输出共两行:
第一行为小A的角色承受boss攻击的次数
第二行一个时间,代表小A的角色最后一次遭受攻击的时间,格式为XX:XX:XX
样例输入
5 60
18:00:00
18:04:30
样例输出
4
18:04:00
样例说明
如样例,boss 每第 60 秒攻击一次,角色第一次受到攻击时 18:01:00,最后一次是18:04:00 。共承受 4 次攻击。
- 时分秒的计算繁琐且十分容易错,我们可以全部转换为秒再进行计算
int miao(int t11,int t22,int t33) //转换为秒 { int miaouu=t33+t22*60+t11*3600; return miaouu; } void biao(int ress) //转换为标准格式 { int h=0,m=0,s=0; while(ress>=3600){ h++; ress-=3600; } while(ress>=60){ m++; ress-=60; } s=ress; printf("%02d:%02d:%02d",h,m,s); } int main() { int x,y,t1,t2,t3,tt1,tt2,tt3,time1,time2,num=0; scanf("%d%d",&x,&y); scanf("%d:%d:%d",&t1,&t2,&t3); scanf("%d:%d:%d",&tt1,&tt2,&tt3); time1=miao(t1,t2,t3); time2=miao(tt1,tt2,tt3); int time=time2-time1; while(time>=y&&x>0){ num++; time-=y; time1+=y; x--; } printf("%d\n",num); biao(time1); return 0; }
1-8 去掉重复的数据
在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,去掉所有重复的数字。最后按照输入顺序输出没有重复数字的数据。所有重复的数字只保留第一次出现的那份。
输入格式:
你的程序首先会读到一个正整数 n,1≤n≤100000。
然后是 n 个整数,这些整数的范围是 [1, 100000]。
输出格式:
在一行中按照输入顺序输出去除重复之后的数据。每两个数据之间有一个空格,行首尾不得有多余空格。
输入样例:
5
1 2 2 1 4
输出样例:
1 2 4
- 题目中数据不大,可以开一个数组,输出答案后,变动数组的值,使其不再输出
同样注意空格问题!int main() { int n,x,arr[100005]={0},num=1; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&x); if(arr[x]==0&&num){ printf("%d",x); num=0; } else if(arr[x]==0){ printf(" %d",x); } arr[x]++; } return 0; }
进阶题
2-1 聚餐
有一个班有 n 个人, 从 1∼n 编号。这学期班里一共举行了 m 次聚餐,第i 次聚餐有 k i个人参加。如果两名同学参加过同一场聚餐,那么我们就说这两个同学是熟悉的。现在给你q次询问,每个询问包含两个同学的编号a、b,问同学a和同学b是否熟悉。
输入格式
第一行三个整数n,m,q(1<=n,m,q<=100)。分别代表同学人数,聚餐次数和询问次数。
接下来m行,每行第一个数 ki代表这次聚餐的人数,后面是 k i个同学的编号。
接下来 q行,每行两个整数 x和 y代表两个同学的编号。(x!=y)
输出格式
输出包含 q行,每行对应一个询问的答案,如果同学a和同学b是熟悉的,输出 YES;否则输出 NO 。
样例输入
3 2 2
2 1 2
2 1 3
1 2
2 3
样例输出
YES
NO
提示
样例中,共有3名学生,2场聚餐,2次询问
第一次聚餐有2名同学参加,分别是同学1和同学2
第二次聚餐有2名同学参加,分别是同学2和同学3
第一次询问,同学1和同学2都参加过第一场聚餐,所以输出YES
第二次询问,同学2和同学3没有参加过同一场聚餐,所以输出NO
- 每次输入记录在arr里,同时使二维数组brr[arr[num1]][arr[num2]]和brr[arr[num2]][arr[num1]]的方式记录和判断两位同学是否熟悉
int main() { int n,m,q,num1,num2,num3; int arr[105],brr[105][105]; scanf("%d%d%d",&n,&m,&q); while(m--){ scanf("%d",&num1); for(int i=1;i<=num1;i++){ scanf("%d",&arr[i]); } for(int i=1;i<=num1;i++){ for(int j=i+1;j<=num1;j++){ brr[arr[i]][arr[j]]=brr[arr[j]][arr[i]]=1; } } } while(q--){ scanf("%d%d",&num2,&num3); puts(brr[num2][num3]?"YES":"NO"); } return 0; }
2-2 捡到两个字符串
小孤独总是喜欢低着头走路,因此经常捡到奇怪的东西,这天她捡到了两只字符串。给出两个由小写字母组成的字符串,一个整数m,以及m个由26个不同的小写字母构成的字符串作代表的新字母表,字符大小关系是按照顺序从小到大。请按照新的字母表以字典序的比较方法来比较,输出较小的字符串,若相同输出任意一个。字典序比较的解释:一个字符串小于另一个字符串,当且仅当以下情况之一成立
1.a是b的前缀,且a!=b。
2.在a和b不同的第一个位置,字符串a有一个字母在字母表中出现的时间比b中的相应字母早。
例如:按照正常的字母表abcdefghijklmnopqrstuvwxyz字符大小从小到大来比较,abc<bcd , aa<aaa , aab>aaa。
输入格式
前两行分别为两个字符串s1,s2(1<=∣s∣<=10000)
第三行为一个整数 m,代表给出m个新的字母表。(1<=m<=100)
接下来m行为m个字母表。
输出格式
对于每一个字母表输出相对应的较小的字符串。
样例输入
aaa
aab
2
abcdefghijklmnopqrstuvwxyz
bacdefghijklmnopqrstuvwxyz
样例输出
aaa
aab
补充
对于前10组测试用例,保证m=1且给定字母表为abcdefghijklmnopqrstuvwxyz,因此你只需要按照正常字典序进行比较
- 本题使用映射的方法解决,将新的规则一个一个字符的转化为数字储存
int main() { int n,flag=0,ys[200];//ys=映射 char arr[1000005],brr[1000005],neww[27];//neww=新规则 scanf("%s",arr); scanf("%s",brr); scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s",neww); for(int j=0;neww[j];j++){ ys[neww[j]]=j; //映射与数字顺序对应 } for(int i=0;arr[i]&&brr[i];i++){ if(ys[arr[i]]<ys[brr[i]]){ flag=1; break; } else if(ys[arr[i]]>ys[brr[i]]){ flag=2; break; } } if(flag==1) printf("%s\n",arr); else if(flag==2) printf("%s\n",brr); else{ if(strlen(arr)<strlen(brr)) printf("%s\n",arr); else printf("%s\n",brr); } } return 0; }
2-3 打印菱形 (Hard-ver)
给定一个 n ,代表菱形的边长,请输出要求大小的图形(详见样例)。
输入格式
输入一行一个整数 n(2<=n<=100) ,代表菱形的边长(数据保证n为偶数)。
输出格式
输出见样例:
样例输入
样例输出
- 热知识:输出“\”需要“\”
int main(){ int n;scanf("%d",&n); // 上半未重合部分 for(int i=1;i<=n/2;i++){ for(int j=1;j<=n-i;j++) printf(" "); printf("/"); for(int j = 1;j<=2*(i-1);j++) printf(" "); printf("\\"); for(int j = 1;j<=n-(i*2-1);j++) printf(" "); printf("/"); for(int j = 1;j<=2*(i-1);j++) printf(" "); printf("\\"); puts(""); } // 上半重合部分 for(int i=n/2+1;i<=n;i++){ for(int j=1;j<= n-i;j++)printf(" "); printf("/"); for(int j=1;j<=n;j++)printf(" "); printf("/"); for(int j=1;j<=2*(i-1);j++)printf(" "); printf("\\"); puts(""); } //下半重合部分 for(int i=1;i<=n/2;i++){ for(int j=1;j<=i-1; j++)printf(" "); printf("\\"); for(int j = 1;j<=n;j++)printf(" "); printf("\\"); for(int j=1;j<=2*(n-i);j++) printf(" "); printf("/"); puts(""); } //下半未重合部分 for (int i=n/2+1;i<=n;i++){ for (int j=1;j<= i-1;j ++ )printf(" "); printf("\\"); for (int j=1;j<=2*(n-i);j++)printf(" "); printf("/"); for (int j=1;j<=n-(2*(n-i)+1);j++)printf(" "); printf("\\"); for (int j=1;j<=2*(n-i);j++)printf(" "); printf("/"); puts(""); } return 0; }
最后四题就不做总结了,为什么捏?大家看看提交率和通过率就知道了。。。