团队天梯赛练习题题解 L1-001~L1-010
前情提要,Python题解思路基本写在代码,新老博客夹杂写出的,风格不统一也正常
两个人思路不一样也很正常,两种思路都可以的,不一定只有这种实现
L1-001 Hello World (5 分)
这道超级简单的题目没有任何输入。
你只需要在一行中输出著名短句Hello World!就可以了。
输入样例
无输出样例
Hello World!作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
PotremZ の C++ 解決策
#include<cstdio>
int main()
{
printf("Hello World!");
return 0;
}winterl の Python 解決策
# 尽量直接复制粘贴,避免手贱,眼花,打错带来的错误
print("Hello World!")L1-002 打印沙漏 (20 分)
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个*,要求按下列格式打印
*****
***
*
***
*****所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差;符号数先从大到小顺序递减到,再从小到大顺序递增;首尾符号数相等。
给定任意个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式
输入在一行给出个正整数和一个符号,中间以空格分隔。
输出格式
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例
19 *输出样例
*****
***
*
***
*****作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
PotremZ’s Solution
-
设定变量
maxs为第一行需要输出的、最大的 符号数; -
遍历寻找
maxs的最大值,对于总的符号数,有公式
公式左边为等差数列求和,是因为要组成沙漏,可以看成上下镜像后将其中一个
*去掉即可;
-
对于空格数量,设当前行需要输出字符数量为
j,则需要输出的空格数量为; -
对于剩余符号数,即;
PotremZ の C++ 解決策
#include<cstdio>
int main()
{
int n,maxs=1; char ch; scanf("%d %c",&n,&ch);
for(;;maxs+=2){
if(n<(1+(maxs+2))*((maxs+2)/2+1)-1) break;
}
for(int i=maxs;i>=1;i-=2){
for(int j=1;j<=(maxs-i)/2;++j) printf(" ");
for(int k=1;k<=i;++k) printf("%c",ch);
puts("");
}
for(int i=3;i<=maxs;i+=2){
for(int j=1;j<=(maxs-i)/2;++j) printf(" ");
for(int k=1;k<=i;++k) printf("%c",ch);
puts("");
}
printf("%d",n-((1+maxs)*(maxs/2+1)-1));
return 0;
}winterl の Python 解決策
n, symbol = input().split()
count = int(n)
# 暴力枚举,求出剩下多少,这里也可以用数学公式推
used = 1
max_width = 1
while used <= count:
max_width += 2
used += max_width * 2
used -= max_width * 2
max_width -= 2
# 计算出剩下多少个,和顶层有多少个
unused = count - used
current_width = max_width
# 打印一层
def show_line(current_width):
space = " " * ((max_width - current_width) // 2)
symbols = symbol * current_width
print(space + symbols)
# 打印沙漏
while current_width > 1:
show_line(current_width)
current_width -= 2
while current_width <= max_width:
show_line(current_width)
current_width += 2
# 打印剩余
print(unused)L1-003 个位数统计 (15 分)
给定一个 位整数 ,请编写程序统计每种不同的个位数字出现的次数。例如:给定 ,则有 个 , 个 ,和 个 。
输入格式
每个输入包含 个测试用例,即一个不超过 位的正整数 。
输出格式
对 中每一种不同的个位数字,以 的格式在一行中输出该位数字 及其在 中出现的次数 。要求按 的升序输出。
输入样例
100311输出样例
0:2
1:3
3:1作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
PotremZ’s Solution
-
因为的位数很大,而且只关注每位上是什么数字,故将作为
string读入; -
随后记录数字出现次数即可;
PotremZ の C++ 解決策
#include<iostream>
using namespace std;
int num[10];
int main()
{
string n; cin>>n;
for(int i=0;i<n.size();++i)
++num[n[i]-'0'];
for(int i=0;i<=9;++i)
if(num[i]) cout<<i<<":"<<num[i]<<endl;
return 0;
}winterl の Python 解決策
number = input()
# 这里在别的语言可以用SortedMap来秒
# 但是Python的字典是无序的,做不到
# 所以需要用离散化的方法
values = list(number)
values.sort()
# 方便处理末尾情况
values.append("")
counter = 0
last_value = values[0]
answer_lines = []
# 扫一遍数字,直接统计就好
for value in values:
if last_value == value:
counter += 1
continue
# elif last_value == -1 or last_value != value
answer_lines.append(f"{last_value}:{counter}")
last_value = value
counter = 1
print("\n".join(answer_lines))L1-004 计算摄氏温度 (5 分)
给定一个华氏温度,本题要求编写程序,计算对应的摄氏温度。计算公式:。题目保证输入与输出均在整型范围内。
输入格式
输入在一行中给出一个华氏温度。
输出格式
在一行中按照格式Celsius = C输出对应的摄氏温度的整数值。
输入样例
150输出样例
Celsius = 65作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
PotremZ の C++ 解決策
#include<cstdio>
int main(){
int F; scanf("%d",&F);
printf("Celsius = %d",5*(F-32)/9);
return 0;
}winterl の Python 解決策
F = int(input())
# 这里是一个神坑,如果用//整除,可能出现结果不对
# 但是除后转成整数就可以对。原因是负数除法的处理不同
# 如 31,整除会向下取整,取 -1,而转换 int 只会保留整数位
print(f"Celsius = {int(5 * (F - 32) / 9)}")L1-005 考试座位号 (15 分)
每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着领到的试机座位号码求助于你,从后台查出他们的考试座位号码。
输入格式
输入第一行给出一个正整数 ,随后 行,每行给出一个考生的信息:准考证号 试机座位号 考试座位号。其中准考证号由 位数字组成,座位从 到 编号。输入保证每个人的准考证号都不同,并且任何时候都不会把两个人分配到同一个座位上。
考生信息之后,给出一个正整数 ,随后一行中给出 个待查询的试机座位号码,以空格分隔。
输出格式
对应每个需要查询的试机座位号码,在一行中输出对应考生的准考证号和考试座位号码,中间用 个空格分隔。
输入样例
4
3310120150912233 2 4
3310120150912119 4 1
3310120150912126 1 3
3310120150912002 3 2
2
3 4输出样例
3310120150912002 2
3310120150912119 1作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:200 ms
内存限制:64 MB
PotremZ’s Solution
-
直接使用STL中的
map,设每个学生有一个学生序号; -
用
map让每个试机座位号都对应一个学生序号,每次寻找直接输出对应学生序号下的准考证号和考试座位号即可;
PotremZ の C++ 解決策
#include<cstdio>
#include<map>
using namespace std;
const int N=1010;
map<int,int>mp;
long long zhun_kao[N];
int shi_ji[N],kao_shi[N];
int main(){
int n; scanf("%d",&n);
while(n--){
scanf("%lld %d %d",&zhun_kao[n],&shi_ji[n],&kao_shi[n]);
mp[shi_ji[n]]=n;
}
int m; scanf("%d",&m);
while(m--){
int Shi_Ji; scanf("%d",&Shi_Ji);
printf("%lld %d\n",zhun_kao[mp[Shi_Ji]],kao_shi[mp[Shi_Ji]]);
}
return 0;
}winterl の Python 解決策
# 容易想到,用一个字典
# 键为查询用的 试机座位号
# 值为 准考证号 和 考试座位号 的元组
machine_table = {}
for _ in range(int(input())):
student_id, machine_id, exam_id = map(int, input().split())
machine_table[machine_id] = (student_id, exam_id)
_ = input() # 可以忽略这一行,不需要这个信息,也可用它来辅助输入
for query_id in map(int, input().split()):
# 每次查询,直接利用字典查就好了
student_id, exam_id = machine_table[query_id]
print(student_id, exam_id)L1-006 连续因子 (20 分)
一个正整数 的因子中可能存在若干连续的数字。例如 可以分解为 ,其中 就是 个连续的数字。给定任一正整数 ,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。
输入格式
输入在一行中给出一个正整数
输出格式
首先在第 行输出最长连续因子的个数;然后在第 行中按 因子1*因子2*……*因子k 的格式输出最小的连续因子序列,其中因子按递增顺序输出, 不算在内。
输入样例
630输出样例
3
5*6*7作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
PotremZ’s Solution
思路来自林夕-梦的天梯赛 L1-006 连续因子 (模拟)
一开始读错题了,以为是要找约数,一个最大连续、一个最小连续
但实际上,就是单纯让分解,求出一个最长连续因子个数,并输出其字典序最小序列;
- 因为需要分解,考虑到,且题目要求不考虑,则序列最长长度即为;
首先它到不了13,所以最大为,又忽略,故为;
-
让序列从最长开始遍历,让因子从遍历到,并按照序列长度累乘(因为如果序列中有数 ,则可能有,显然非法);
-
这样,当找到一组合法解时,此解必然为最长序列,且其字典序最小;
PotremZ の C++ 解決策
#include<cstdio>
#define ll long long
int main(){
int n; scanf("%d",&n);
for(int len=11;len>=1;--len){
for(ll i=2;i*i<=n;++i){
ll res=1;
for(int j=i;j<=i+len-1;++j){
res*=j;
if(res>n) break;
}
if(n%res==0){
printf("%d\n",len);
for(int j=i;j<=i+len-1;++j)
printf("%d%c",j,j==i+len-1? 0 : '*');
return 0;
}
}
}
printf("1\n%d",n);
return 0;
}winterl の Python 解決策
n = int(input())
# 朴素分解因子的时间复杂度是 O(n)
# 数据范围比较大,应该采用一个小于 O(n) 的算法
# 可以采用开根优化来分解因子
# 求从 start 开始的连续因子列表
def get_lined_factors(start):
num = n
result = []
current = start
while num % current == 0:
num //= current
# 用字符串是为了方便后续的输出
result.append(str(current))
current += 1
return result
answer = []
# 枚举每个因子起点
for start in range(2, int(n ** 0.5) + 1):
factors = get_lined_factors(start)
if len(factors) > len(answer):
answer = factors
# 是素数(质数)的情况
length = len(answer)
if length == 0:
print(1)
print(n)
else:
print(length)
print("*".join(answer))L1-007 念数字 (10 分)
输入一个整数,输出每个数字对应的拼音。当整数为负数时,先输出fu字。十个数字对应的拼音如下:
0: ling
1: yi
2: er
3: san
4: si
5: wu
6: liu
7: qi
8: ba
9: jiu输入格式
输入在一行中给出一个整数,如:1234。
提示:整数包括负数、零和正数。
输出格式
在一行中输出这个整数对应的拼音,每个数字的拼音之间用空格分开,行末没有最后的空格。如 yi er san si。
输入样例
-600输出样例
fu liu ling ling作者:翁恺
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
PotremZ’s Solution
-
使用
map预处理对应拼音,使用string读入; -
随后遍历,注意行末没有空格即可;
PotremZ の C++ 解決策
#include<cstdio>
#include<iostream>
#include<map>
using namespace std;
map<int,string>mp;
int main(){
mp[0]="ling";
mp[1]="yi";
mp[2]="er";
mp[3]="san";
mp[4]="si";
mp[5]="wu";
mp[6]="liu";
mp[7]="qi";
mp[8]="ba";
mp[9]="jiu";
mp[10]="fu";
string n; cin>>n;
for(int i=0;i<n.size();++i){
if(n[i]=='-') cout<<mp[10];
else cout<<mp[n[i]-'0'];
printf("%c",i==n.size()-1 ? 0 : ' ');
}
return 0;
}winterl の Python 解決策
# 打一个字典表,后面直接查就完了
PINYIN_MAP = {
"0": "ling",
"1": "yi",
"2": "er",
"3": "san",
"4": "si",
"5": "wu",
"6": "liu",
"7": "qi",
"8": "ba",
"9": "jiu",
"-": "fu",
}
answer = []
for char in input():
answer.append(PINYIN_MAP[char])
print(" ".join(answer))L1-008 求整数段和 (10 分)
给定两个整数和,输出从到的所有整数以及这些数的和。
输入格式
输入在一行中给个整数和,其中,其间以空格分隔。
输出格式
首先顺序输出从A到B的所有整数,每个数字占一行,每个数字占个字符宽度,向右对齐。最后在一行中按Sum = X的格式输出全部数字的和X。
输入样例
-3 8输出样例
-3 -2 -1 0 1
2 3 4 5 6
7 8
Sum = 30作者:杨起帆
单位:浙大城市学院
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
PotremZ の C++ 解決策
#include<cstdio>
int main(){
int a,b; scanf("%d %d",&a,&b);
int i=a;
while(i<=b){
for(int j=1;j<=5;++j){
printf("%5d",i); if(j==5) puts("");
++i;
if(i==b+1){
if(j!=5) puts("");
printf("Sum = %d",(a+b)*(b-a+1)/2);
return 0;
}
}
}
return 0;
}winterl の Python 解決策
lower, upper = map(int, input().split())
total = 0
counter = 0 # 记录一行打了多少个
for value in range(lower, upper + 1):
total += value
if counter == 5:
counter = 0
print()
# 格式化字符串,保留五位宽度
print(f"{value:>5}", end="")
counter += 1
print(f"\nSum = {total}")L1-009 N个数求和 (20 分)
本题的要求很简单,就是求N个数字的和。麻烦的是,这些数字是以有理数分子/分母的形式给出的,你输出的和也必须是有理数的形式。
输入格式
输入第一行给出一个正整数N。随后一行按格式a1/b1 a2/b2 ...给出N个有理数。题目保证所有分子和分母都在长整型范围内。另外,负数的符号一定出现在分子前面。
输出格式
输出上述数字和的最简形式 —— 即将结果写成整数部分 分数部分,其中分数部分写成分子/分母,要求分子小于分母,且它们没有公因子。如果结果的整数部分为,则只输出分数部分。
输入样例1
5
2/5 4/15 1/30 -2/60 8/3输出样例1
3 1/3输入样例2
2
4/3 2/3输出样例2
2输入样例3
3
1/3 -1/6 1/8输出样例3
7/24作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
PotremZ’s Solution
思路来自 ChangeG 的N个数求和(PTA)
1.对当前读入的有理数,直接与之前输入的有理数相加,再化为最简形式;
2.设之前输入的有理数的和的形式为,当前读入的有理数为
3.显然通分结果为,则通分后,两数分别为,则合并结果为;
4.对于累加后的 新的,设,则为的最大公因子,上下同除可以使分数最简化;
5.最后对整数部分进行判断,注意输出格式即可;
原博主这么写过:
-3/2的时候他们的结果都是-1 1/-2,但他给出的代码会输出-1 1/2,本人认为答案应该为-1 -1/2,因为一般认为最简形式其实应该为整数部分+分数部分,所以分数部分也应是负数;
PotremZ の C++ 解決策
#include<cstdio>
#include<algorithm>
#define ll long long
ll a,b,suma,sumb=1;
ll gcd(ll x,ll y){ return y==0 ? x : gcd(y,x%y); }
int main(){
int n; scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%lld/%lld",&a,&b);
suma=suma*b+a*sumb;
sumb=sumb*b;
ll tmp=gcd(suma,sumb);
suma/=tmp; sumb/=tmp;
}
if(suma==0) puts("0");//特判0
else {
if(suma/sumb) printf("%lld",suma/sumb);
if(suma%sumb){
if(suma/sumb) printf(" ");//格式格式
if(suma*sumb<0) printf("-");
printf("%lld/%lld\n",abs(suma%sumb),abs(sumb));
}
}
return 0;
}winterl の Python 解決策
# 标准库大法,Python最大的优势就是标准库,一定要好好利用
from fractions import Fraction
_ = input()
# 不用标准库 这里就需要先把分子分母分开存
fractions = map(Fraction, input().split())
# 直接计算求和,并且求出分子分母
top, bottom = sum(fractions).as_integer_ratio()
if bottom == 1: # 分子为 1 表示是一个整数
print(top)
else:
# 注意,不要用自带的整除,或者divmod,神坑
div = int(top / bottom)
mod = top - div * bottom
if div != 0: # 是一个带分数
print(div, f"{mod}/{bottom}")
else:
print(f"{mod}/{bottom}")L1-010 比较大小 (10 分)
本题要求将输入的任意个整数从小到大输出。
输入格式
输入在一行中给出个整数,其间以空格分隔。
输出格式
在一行中将个整数从小到大输出,其间以->相连。
输入样例
4 2 8输出样例
2->4->8作者:杨起帆
单位:浙大城市学院
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB
PotremZ の C++ 解決策
#include<cstdio>
#include<algorithm>
int main(){
int x[3]; scanf("%d %d %d",&x[0],&x[1],&x[2]);
std::sort(x,x+3);
printf("%d->%d->%d",x[0],x[1],x[2]);
return 0;
}winterl の Python 解決策
# 水题,秒了(bushi)
print("->".join(map(str, sorted(map(int, input().split())))))
# lst = map(int, input().split())
# lst = sorted(lst)
# str_lst = map(str, lst)
# print("->".join(str_lst))