团队天梯赛练习题题解 L1-011~L1-020

前情提要,Python题解思路基本写在代码,新老博客夹杂写出的,风格不统一也正常
两个人思路不一样也很正常,两种思路都可以的,不一定只有这种实现

L1-011 A-B (20 分)

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

输入格式

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

输出格式

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

输入样例

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

输出样例

I lv GPLT!  It's  fn gm!

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:150 ms
内存限制:64 MB

数据很小,直接暴力即可;

PotremZ の C++ 解決策

#include<iostream>
#include<algorithm>
using namespace std;
string A,B,ans;
bool check(char ch){
	for(int i=0;i<B.size();++i)
		if(ch==B[i]) return 0;
	return 1;
}
int main(){
	getline(cin,A);
	getline(cin,B);
	for(int i=0;i<A.size();++i)
		if(check(A[i])) ans+=A[i];
	cout<<ans;
	return 0;
}

winterl の Python 解決策

line = input()
# 用一个 (hash)set 可以加速查询,当然,用别的东西应该也可以过的
whitespace = set(input())
for char in line:
    # 是空白符就跳过
    if char in whitespace:
        continue
    # 否则打印
    print(char, end="")

L1-012 计算指数 (5 分)

真的没骗你,这道才是简单题 —— 对任意给定的不超过 1010 的正整数 nn,要求你输出 2n2^n。不难吧?

输入格式

输入在一行中给出一个不超过 1010 的正整数 nn

输出格式

在一行中按照格式 2^n = 计算结果 输出 2n2^n 的值。

输入样例

5

输出样例

2^5 = 32

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB

这里使用了快速幂的模板(其实不需要);

PotremZ の C++ 解決策

#include<iostream>
#include<algorithm>
using namespace std;
int pow(int x,int k){
	int res=1;
	while(k){
		if(k&1) res=res*x;
		x*=x;
		k>>=1;
	}
	return res;
}
int main(){
	int n; scanf("%d",&n);
	printf("2^%d = %d",n,pow(2,n));
	return 0;
}

winterl の Python 解決策

n = int(input())
# 格式化字符串快速运用,这里用到一个二进制移位运算
# 1 << n 就是 2**n,位运算相关的可以自己了解
print(f"2^{n} = {1 << n}")

L1-013 计算阶乘和 (10 分)

对于给定的正整数N,需要你计算 S=1!+2!+3!+...+N!S=1!+2!+3!+...+N!

输入格式

输入在一行中给出一个不超过1010的正整数NN

输出格式

在一行中输出SS的值。

输入样例

3

输出样例

9

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB

res代表i!i!

PotremZ の C++ 解決策

#include<cstdio>
int main(){
	int n; long long res=1,ans=1; 
	scanf("%d",&n);
	for(int i=2;i<=n;++i) ans=ans+(res*=i);
	printf("%lld",ans);
	return 0;
}

winterl の Python 解決策

n = int(input())
answer, current = 0, 1
# 这里也可以用标准库的阶乘函数计算,不过没必要了,效率低
for i in range(1, n + 1):
    current *= i
    answer += current
print(answer)

L1-014 简单题 (5 分)

这次真的没骗你 —— 这道超级简单的题目没有任何输入。

你只需要在一行中输出事实:This is a simple problem. 就可以了。

输入样例

输出样例

This is a simple problem.

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB

PotremZ の C++ 解決策

#include<cstdio>
int main(){
	printf("This is a simple problem.");
	return 0;
}

winterl の Python 解決策

# 大 签 到
# print("This is a simple problem.")

# 以下是整活,不要学
from base64 import b64decode as decode
print(str(decode("VGhpcyBpcyBhIHNpbXBsZSBwcm9ibGVtLg=="), 'utf-8'))

L1-015 跟奥巴马一起画方块 (15 分)

美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统。20142014年底,为庆祝“计算机科学教育周”正式启动,奥巴马编写了很简单的计算机代码:在屏幕上画一个正方形。现在你也跟他一起画吧!

输入格式

输入在一行中给出正方形边长N(3N21)N(3 \leqslant N \leqslant 21)和组成正方形边的某种字符C,间隔一个空格。

输出格式

输出由给定字符C画出的正方形。但是注意到行间距比列间距大,所以为了让结果看上去更像正方形,我们输出的行数实际上是列数的50%50\%(四舍五入取整)。

输入样例

10 a

输出样例

aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB

注意题目要求四舍五入;

PotremZ の C++ 解決策

#include<cstdio>
int main(){
	int n; char c;
	scanf("%d %c",&n,&c);
	for(int i=1;i<=(n+1)/2;++i){
		for(int j=1;j<=n;++j)
			printf("%c",c);
		puts("");
	}
	return 0;
}

winterl の Python 解決策

n, char = input().split()
width = int(n)
# 显而易见的是 50%(四舍五入取整)就是奇偶性判断,偶数直接除,奇数还要加 1
# 右移 1 表示除 2, 按位与 1 表示判断奇数,奇数返回 1,偶数返回 0
high = (width >> 1) + (width & 1)
# 字符串乘法实现快速简单的复制,小心坑人的换行
print(((char * width) + '\n') * high, end="")

L1-016 查验身份证 (15 分)

一个合法的身份证号码由1717位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:

首先对前1717位数字加权求和,权重分配为:{7910584216379105842}\{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2\};然后将计算的和对1111取模得到值Z;最后按照以下关系对应Z值与校验码M的值:

Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2

现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。

输入格式

输入第一行给出正整数N(100)N( \leqslant 100)是输入的身份证号码的个数。随后NN行,每行给出111818位身份证号码。

输出格式

按照输入的顺序每行输出11个有问题的身份证号码。这里并不检验前1717位是否合理,只检查前1717位是否全为数字且最后11位校验码计算准确。如果所有号码都正常,则输出All passed

输入样例1

4
320124198808240056
12010X198901011234
110108196711301866
37070419881216001X

输出样例1

12010X198901011234
110108196711301866
37070419881216001X

输入样例2

2
320124198808240056
110108196711301862

输出样例2

All passed

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB

直接按照题意模拟代换即可;

注意前1717应该需要判断是否全为数字,感谢zwy提供的数据:

>1
>abcdefghijklmnopq7

这个身份证号显然不正常,但如果没有判断前1717是否为数字,可能会被认为是正常的

PotremZ の C++ 解決策

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int W[18]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
int Z[11]={1,0,10,9,8,7,6,5,4,3,2};
int main(){
	int n,cnt=0; scanf("%d",&n);
	while(n--){
		string s; cin>>s;
		int res=0; bool f=0;
		for(int i=0;i<17;++i){
			res+=(s[i]-'0')*W[i];
			if(s[i]<'0'||s[i]>'9') f=1; 
		}
		res%=11;
		if((Z[res]==(s[17]-'0')||(Z[res]==10&&s[17]=='X'))&&!f) continue;
		cout<<s<<endl; ++cnt;
	}
	if(!cnt) puts("All passed");
	return 0;
}

winterl の Python 解決策

# 先打表,存下来要用的东西
WEIGHT = (7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
MARK = ("1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2")

# 假设它能全部用过,记录一下
is_passed = True
for _ in range(int(input())):
    token = input()
    code, is_digits = 0, True
    # 计算一下我们的效验码
    for index in range(17):
        is_digits = token[index].isdigit()
        if not is_digits:
            break
        value = int(token[index])
        code += value * WEIGHT[index]
    code %= 11
    # 全是数字 并且 效验码正确,说明没有错误
    if is_digits and MARK[code] == token[-1]:
        continue
    # 效验码错误,证明不能全部通过了
    is_passed = False
    print(token)

if is_passed:
    print("All passed")

L1-017 到底有多二 (15 分)

一个整数“犯二的程度”定义为该数字中包含22的个数与其位数的比值。如果这个数是负数,则程度增加0.50.5倍;如果还是个偶数,则再增加11倍。例如数字-13142223336是个1111位数,其中有3个2,并且是负数,也是偶数,则它的犯二程度计算为:3/11×1.5×2×100%3/11×1.5×2×100\%,约为81.82%81.82\%。本题就请你计算一个给定整数到底有多二。

输入格式

输入第一行给出一个不超过5050位的整数N

输出格式

在一行中输出N犯二的程度,保留小数点后两位。

输入样例

-13142223336

输出样例

81.82%

鸣谢安阳师范学院段晓云老师和软件工程五班李富龙同学补充测试数据!

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB

直接模拟即可;

PotremZ の C++ 解決策

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
	string n; cin>>n;
	
	int len=n.size(),cnt2=0;
	bool even=0,fu=0;
	
	for(int i=0;i<len;++i)
		if(n[i]=='2') ++cnt2;
		
	if((n[len-1]-'0')%2==0) even=1;//这两个if顺序不可颠倒
	if(n[0]=='-') --len,fu=1;
	
	double ans=1.0*cnt2/len;
	if(fu) ans*=1.5;
	if(even) ans*=2.0;
	printf("%.2lf%%",ans*100);
	return 0;
}

winterl の Python 解決策

two_counter = 0  # 记录 2 的个数
length = 0
negative_effect = 1  # 负数的影响
even_effect = 1  # 偶数的影响

number = input()
length = len(number)
# 计算偶数个数
for digit in number:
    if digit == "2":
        two_counter += 1
# 检查负数
if number[0] == "-":
    negative_effect = 1.5
    # 记得负数要去掉负号带来的长度影响
    length -= 1
# 检查偶数
if int(number[-1]) & 1 == 0:
    even_effect = 2

print(f"{two_counter / length * negative_effect * even_effect * 100:.2f}%")

L1-018 大笨钟 (10 分)

微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。不过由于笨钟自己作息也不是很规律,所以敲钟并不定时。一般敲钟的点数是根据敲钟时间而定的,如果正好在某个整点敲,那么“当”数就等于那个整点数;如果过了整点,就敲下一个整点数。另外,虽然一天有2424小时,钟却是只在后半天敲1121 \sim 12下。例如在23:0023:00敲钟,就是“当当当当当当当当当当当”,而到了23:0123:01就会是“当当当当当当当当当当当当”。在午夜00:0000:00到中午12:0012:00期间(端点时间包括在内),笨钟是不敲的。

下面就请你写个程序,根据当前时间替大笨钟敲钟。

输入格式

输入第一行按照hh:mm的格式给出当前时间。其中hh是小时,在00002323之间;mm是分钟,在00005959之间。

输出格式

根据当前时间替大笨钟敲钟,即在一行中输出相应数量个Dang。如果不是敲钟期,则输出:

Only hh:mm.  Too early to Dang.

其中hh:mm是输入的时间。

输入样例1

19:05

输出样例1

DangDangDangDangDangDangDangDang

输入样例2

07:05

输出样例2

Only 07:05.  Too early to Dang.

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB

PotremZ の C++ 解決策

#include<cstdio>
int main(){
	int hh,mm;
	scanf("%d:%d",&hh,&mm);
	if(hh<=11||(hh==12&&mm==0)) printf("Only %02d:%02d.  Too early to Dang.",hh,mm);
	else{
		for(int i=1;i<=hh-12;++i) printf("Dang");
		if(mm) printf("Dang");
	}
	return 0;
}

winterl の Python 解決策

# 可以用 split 指定参数来快速获得输入中的时间信息
hour, minute = map(int, input().split(":"))
# 判断一下到点前不能敲钟的情况
if hour < 12 or (hour == 12 and minute == 0):
    # 随便一个格式化字符串方法都行
    print(f"Only {hour:0>2}:{minute:0>2}.  Too early to Dang.")
    exit(0)
# 计算一下 我们需要敲多少下
count = hour - 12 + (1 if minute > 0 else 0)
print("Dang" * count)

L1-019 谁先倒 (15 分)

划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就输了,输家罚一杯酒。两人同赢或两人同输则继续下一轮,直到唯一的赢家出现。

下面给出甲、乙两人的酒量(最多能喝多少杯不倒)和划拳记录,请你判断两个人谁先倒。

输入格式

输入第一行先后给出甲、乙两人的酒量(不超过100100的非负整数),以空格分隔。下一行给出一个正整数N(≤100),随后N行,每行给出一轮划拳的记录,格式为:

甲喊 甲划 乙喊 乙划

其中是喊出的数字,是划出的数字,均为不超过100100的正整数(两只手一起划)。

输出格式

在第一行中输出先倒下的那个人:A代表甲,B代表乙。第二行中输出没倒的那个人喝了多少杯。题目保证有一个人倒下。注意程序处理到有人倒下就终止,后面的数据不必处理。

输入样例

1 1
6
8 10 9 12
5 10 5 10
3 8 5 12
12 18 1 13
4 16 12 15
15 1 1 16

输出样例

A
1

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB

PotremZ の C++ 解決策

#include<cstdio>
int main(){
	int Ajiu_liang,Bjiu_liang;
	scanf("%d %d",&Ajiu_liang,&Bjiu_liang);
	
	int n,Ahan,Ahua,Ahe=0,Bhan,Bhua,Bhe=0; 
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d %d %d %d",&Ahan,&Ahua,&Bhan,&Bhua);
		if((Ahan+Bhan)==Ahua&&(Ahan+Bhan)!=Bhua) ++Ahe;
		if((Ahan+Bhan)!=Ahua&&(Ahan+Bhan)==Bhua) ++Bhe;
		if(Ahe>Ajiu_liang){
			printf("A\n%d",Bhe);
			return 0;
		}
		if(Bhe>Bjiu_liang){
			printf("B\n%d",Ahe);
			return 0;
		}
	}
	return 0;
}

winterl の Python 解決策

# 储存他们的酒量
capacity_of_a, capacity_of_b = map(int, input().split())
drink_of_a, drink_of_b = 0, 0 # 他们喝了多少
for _ in range(int(input())):
    call_of_a, write_of_a, call_of_b, write_of_b = map(int, input().split())
    total = call_of_a + call_of_b # 甲乙两人喊出的数字之和
    # 他们两有一个要喝酒
    if write_of_a == total and write_of_b != total:
        drink_of_a += 1
    if write_of_a != total and write_of_b == total:
        drink_of_b += 1
    # 有一个醉了,打印结果。 一定要记得退出程序
    if drink_of_a > capacity_of_a:
        print("A")
        print(drink_of_b)
        break
    if drink_of_b > capacity_of_b:
        print("B")
        print(drink_of_a)
        break

L1-020 帅到没朋友 (20 分)

当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友。本题就要求你找出那些帅到没有朋友的人。

输入格式

输入第一行给出一个正整数N(100)( \leqslant 100),是已知朋友圈的个数;随后N行,每行首先给出一个正整数K(1000)(\leqslant 1000),为朋友圈中的人数,然后列出一个朋友圈内的所有人——为方便起见,每人对应一个ID号,为55位数字(从00000000009999999999),ID间以空格分隔;之后给出一个正整数M(10000)( \leqslant 10000),为待查询的人数;随后一行中列出M个待查询的ID,以空格分隔。

注意:没有朋友的人可以是根本没安装“朋友圈”,也可以是只有自己一个人在朋友圈的人。虽然有个别自恋狂会自己把自己反复加进朋友圈,但题目保证所有K超过11的朋友圈里都至少有2个不同的人。

输出格式

按输入的顺序输出那些帅到没朋友的人。ID间用11个空格分隔,行的首尾不得有多余空格。如果没有人太帅,则输出No one is handsome

注意:同一个人可以被查询多次,但只输出一次。

输入样例1

3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
8
55555 44444 10000 88888 22222 11111 23333 88888

输出样例1

10000 88888 23333

输入样例2

3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
4
55555 44444 22222 11111

输出样例2

No one is handsome

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:200 ms
内存限制:64 MB

使用vis[]记录重复ID即可;

PotremZ の C++ 解決策

#include<cstdio>
int ans[10005];
bool vis[100000];
int main(){
	int n,ID; scanf("%d",&n);
	for(int i=1;i<=n;++i){
		int k; scanf("%d",&k);
		if(k==1) scanf("%d",&ID);
		else 
			for(int j=1;j<=k;++j){
				scanf("%d",&ID);
				vis[ID]=1;
			}
	}
	int m; scanf("%d",&m);
	for(int i=1;i<=m;++i){
		scanf("%d",&ID);
		if(!vis[ID]){
			ans[++ans[0]]=ID;
			vis[ID]=1;
		}
	}
	if(!ans[0]) printf("No one is handsome");
	else{
		for(int i=1;i<=ans[0];++i)
			if(i!=ans[0]) printf("%05d ",ans[i]);
			else printf("%05d",ans[i]);
	}
	return 0;
}

winterl の Python 解決策

friend_zone = set()
for _ in range(int(input())):
    line = input().split()
    # 坑人哈 一个人自己不能算有朋友圈 要特判一下
    if len(line) == 2:
        continue
    # 将他们都加入有朋友圈的集合中
    for friend_id in line[1:]:
        friend_zone.add(friend_id)

# 又是一个究极神坑,single_one 这里不能用 set ,不然过不了
# 陈越的坑人数据压根没考虑乱序的情况,也没说明顺序

single_one = []
_ = input()
for friend_id in input().split():
    if friend_id in friend_zone:
        continue
    friend_zone.add(friend_id)
    # 然后这个数字可能还不是 5 位长,记得补 0
    single_one.append("{:>05}".format(friend_id))

if len(single_one) == 0:
    print("No one is handsome")
else:
    print(*single_one)

团队天梯赛练习题题解 L1-011~L1-020
https://winterl-blog.netlify.app/2025/01/20/团队天梯赛练习题题解 L1-011~L1-020/
作者
PotremZ, winterl
发布于
2025年1月20日
许可协议