PAT乙级python编程练习(四)
1016 部分A+B
正整数 A 的“DA(为 1 位整数)部分”定义为由 A 中所有 DA组成的新整数 PA。例如:给定 A=3862767,DA=6,则 A 的“6 部分”PA是 66,因为 A 中有 2 个 6。
现给定 A、DA 、B、DB ,请编写程序计算 PA +PB 。
输入格式:
输入在一行中依次给出 A、DA 、B、DB ,中间以空格分隔,其中 0 < A,B < 10^10 。
输出格式:
在一行中输出 PA +PB 的值。
输入样例 1:
3862767 6 13530293 3
输出样例 1:
399
输入样例 2:
3862767 1 13530293 8
输出样例 2:
0
思路及注意点
- 代码中 pa = pa*10 + da 要比 pa = pa + da * 10 ** i 要好。
代码
s = input().split()
pa = pb = 0
da = int(s[1])
db = int(s[3])
for c in s[0]:
if c == s[1]:
pa = pa*10 + da
for c in s[2]:
if c == s[3]:
pb = pb*10 + db
print(pa+pb)
运行结果
测试点 | 结果 | 耗时 | 内存 |
---|---|---|---|
0 | 答案正确 | 23 ms | 3056KB |
1 | 答案正确 | 22 ms | 3064KB |
2 | 答案正确 | 22 ms | 3076KB |
3 | 答案正确 | 22 ms | 3168KB |
4 | 答案正确 | 22 ms | 3056KB |
1017 A除以B
本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数。你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立。
输入格式:
输入在一行中依次给出 A 和 B,中间以 1 空格分隔。
输出格式:
在一行中依次输出 Q 和 R,中间以 1 空格分隔。
输入样例:
123456789050987654321 7
输出样例:
17636684150141093474 3
思路及注意点
- 对于输入的数从高位到低位,依次加上之前的余数*10,再去整除B,得到的商为该位的输出,余数*10加到下一位的计算中。
- 最后结果若最高为为0,则忽略这位的0输出。
代码
s = input().split()
d = list(map(str, range(10)))
a = list(map(int, s[0]))
b = int(s[1])
result = ''
r = 0
for x in a:
num = r*10+x
q = num // b
r = num % b
result += d[q]
if result[0] == '0' and len(result) > 1:
result = result[1:]
print(result, r)
运行结果
测试点 | 结果 | 耗时 | 内存 |
---|---|---|---|
0 | 答案正确 | 24 ms | 3056KB |
1 | 答案正确 | 23 ms | 3156KB |
2 | 答案正确 | 22 ms | 3056KB |
3 | 答案正确 | 25 ms | 3120KB |
4 | 答案正确 | 23 ms | 3076KB |
1018 锤子剪刀布
大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示:
现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。
输入格式:
输入第1行给出正整数N(<=10^5^),即双方交锋的次数。随后N行,每行给出一次交锋的信息,即甲、乙双方同时给出的的手势。C代表“锤子”、J代表“剪刀”、B代表“布”,第1个字母代表甲方,第2个代表乙方,中间有1个空格。
输出格式:
输出第1、2行分别给出甲、乙的胜、平、负次数,数字间以1个空格分隔。第3行给出两个字母,分别代表甲、乙获胜次数最多的手势,中间有1个空格。如果解不唯一,则输出按字母序最小的解。
输入样例:
10
C J
J B
C B
B B
B C
C C
C B
J B
B C
J J
输出样例:
5 3 2
2 3 5
B B
思路及注意点
- 用一个count列表来记录甲的胜平负次数,乙的只需要反向输出即可。
- 用两个字典分别存储甲乙三种手势的获胜次数。排序用到了前面博客提到过的operator模块的itemgetter方法,先根据获胜次数排序,再根据字母序排序。
- 最后一个测试点运行超时,目前我还没找到解决方法。。。求助大佬!(通过1005和这题,深深感觉到这套题在运行时间限制上对python的不友好【捂脸.jpg】,明明和c++一样的算法python运行时间能长好多。虽然说有些题目python能很快解决,比如大整数运算、正则表达式什么的。总之有得必有失。)
代码
#from time import time
n = int(input())
#t1 = time()
from operator import itemgetter
d1 = {'C':0, 'J':0, 'B':0}
d2 = {'C':0, 'J':0, 'B':0}
#0 胜 1 平 2 负
d = {'C C':1, 'C J':0, 'C B':2,
'J C':2, 'J J':1, 'J B':0,
'B C':0, 'B J':2, 'B B':1}
count = [0] * 3
while n:
n -= 1
s = input()
idx = d[s]
count[idx] += 1
if idx == 0:
d1[s[0]] -= 1
elif idx == 2:
d2[s[2]] -= 1
print(count[0], count[1], count[2])
print(count[2], count[1], count[0])
item1, item2 = list(d1.items()), list(d2.items())
item1.sort(key=itemgetter(1,0))
item2.sort(key=itemgetter(1,0))
print(item1[0][0], item2[0][0])
#t2 = time()
#print(t2-t1)
运行结果
测试点 | 结果 | 耗时 | 内存 |
---|---|---|---|
0 | 答案正确 | 25 ms | 3192KB |
1 | 答案正确 | 24 ms | 3204KB |
2 | 答案正确 | 24 ms | 3204KB |
3 | 答案正确 | 24 ms | 3168KB |
4 | 答案正确 | 23 ms | 3204KB |
5 | 运行超时 | 0 ms | 0KB |
1019 数字黑洞
给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到一个新的数字。一直重复这样做,我们很快会停在有“数字黑洞”之称的6174,这个神奇的数字也叫Kaprekar常数。
例如,我们从6767开始,将得到
7766 - 6677 = 1089\ 9810 - 0189 = 9621\ 9621 - 1269 = 8352\ 8532 - 2358 = 6174\ 7641 - 1467 = 6174\ … …
现给定任意4位正整数,请编写程序演示到达黑洞的过程。
输入格式:
输入给出一个(0, 10000)区间内的正整数N。
输出格式:
如果N的4位数字全相等,则在一行内输出“N - N = 0000”;否则将计算的每一步在一行内输出,直到6174作为差出现,输出格式见样例。注意每个数字按4位数格式输出。
输入样例1:
6767
输出样例1:
7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174
输入样例2:
2222
输出样例2:
2222 - 2222 = 0000
思路及注意点
- 最初的输入可能不足四位。步骤中不足四位的均要填补0.
- 用到了字符串的join方法,join其实是split的逆方法
>>> ''.join(['1','2','3'])
'123'
>>> '+'.join(['1','2','3'])
'1+2+3'
代码
s = input()
if len(s) < 4:
s += '0' * (4-len(s))
n1 = int(''.join(sorted(s, reverse=True)))
n2 = int(''.join(sorted(s)))
if n1 == n2:
print('%04d - %04d = 0000' % (n1, n2))
else:
while 1:
r = n1 - n2
print('%04d - %04d = %04d' % (n1, n2, r))
if r == 6174:
break
s = str(r)
if len(s) < 4:
s += '0' * (4-len(s))
n1 = int(''.join(sorted(s, reverse=True)))
n2 = int(''.join(sorted(s)))
运行结果
测试点 | 结果 | 耗时 | 内存 |
---|---|---|---|
0 | 答案正确 | 24 ms | 3100KB |
1 | 答案正确 | 23 ms | 3076KB |
2 | 答案正确 | 23 ms | 3056KB |
3 | 答案正确 | 24 ms | 3056KB |
4 | 答案正确 | 24 ms | 3284KB |
5 | 答案正确 | 25 ms | 3412KB |
6 | 答案正确 | 24 ms | 3180KB |
1020 月饼
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得 72 + 45/2 = 94.5(亿元)。
输入格式:
每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出格式:
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。
输入样例:
3 20
18 15 10
75 72 45
输出样例:
94.50
思路及注意点
- 每种月饼保存成一个元组,包含月饼的库存、总售价和单价。根据单价从小到大排序,优先选择排序后的序列中靠后的元组,因此可以使用列表的pop方法。
- 注意月饼的库存量和总售价题目中只说是正数,不一定是正整数,因此要用float。
- 注意所有月饼的库存仍不满足需求的情况。
代码
s = input().split()
n = int(s[0])
d = int(s[1])
l = [()] * n
c = list(map(float, input().split()))
p = list(map(float, input().split()))
for i in range(n):
l[i] = (c[i], p[i], p[i]/c[i])
l.sort(key=lambda x: x[2])
num = 0
price = 0
while num < d:
item = l.pop()
if num + item[0] <= d:
num += item[0]
price += item[1]
else:
price += item[2] * (d-num)
num = d
if not l:
break
print('%.2f' % price)
运行结果
测试点 | 结果 | 耗时 | 内存 |
---|---|---|---|
0 | 答案正确 | 34 ms | 3156KB |
1 | 答案正确 | 27 ms | 3296KB |
2 | 答案正确 | 23 ms | 3056KB |
3 | 答案正确 | 24 ms | 3376KB |
4 | 答案正确 | 26 ms | 3472KB |