【Educoder作业】Python问题求解模拟测试二
本次测试难度适中,有些题如果深入思考可收获很多。
T1 求立方根
简单题,按照题目要求模拟即可。
def cube(x):
###########请在此行之后编写程序###########
##切勿在此部分代码中使用input和print语句##
g1 = x / 3
g2 = 2 / 3 * g1 + x / (3 * g1 ** 2)
while abs(g1 - g2) > 10 ** (-6) :
g1 = g2
g2 = 2 / 3 * g1 + x / (3 * g1 ** 2)
return g2
###########请在此行之前编写程序###########
if __name__ == '__main__':
#此行之后的代码用于测试运行结果,可根据个人需要添加调试代码,包括使用input和print语句
x=eval(input())
print('%.6f' % (cube(x)))
T2 寻找嫌疑犯
这个题就很好了。
如果只看到表面的话,这题其实是个垃圾题。原因在于我们没有一个很好的办法对于这六个人同时判断;其次,计算机的逻辑是建立在程序的逻辑上的,所以我们只能通过代码的低级逻辑实现这个题里的高级逻辑。
那正常来讲这个题应该怎么做呢?
其实说简单也很简单,只需要用六个循环就行,每个循环代表一个人、从
0
0
0到
1
1
1枚举,在最里面,我们就有六个循环变量了,对于这六个我们再对应所有的条件判断判断就好了,代码如下:
def find():
for A in range(2) :
for B in range(2) :
for C in range(2) :
for D in range(2) :
for E in range(2) :
for F in range(2) :
flag = True
if not A and not B :
flag = False
if A and D :
flag = False
if A + E + F < 2 :
flag = False
if B + C == 1 :
flag = False
if C + D != 1 :
flag = False
if not D and E :
flag = False
if flag :
ret = []
if A :
ret.append('A')
if B :
ret.append('B')
if C :
ret.append('C')
if D :
ret.append('D')
if E :
ret.append('E')
if F :
ret.append('F')
return ret
###########请在此行之前编写程序###########
if __name__ == '__main__':
#此行之后的代码用于测试运行结果,可根据个人需要添加调试代码,包括使用input和print语句
print(find())
你看,长吧。但我都这么说了肯定是有更好的办法,比如说现在不是
6
6
6人,是
20
20
20个人呢?我们难道要写
20
20
20个循环吗?
显然不是,这里介绍一种想法,可能初次看很难理解——状态压缩
还记得我们之前讲过的二进制么,就是每一个十进制对应一个二进制,二者之间是一一对应的关系。而二进制是不是跟我们现在干的事儿有点儿像?我们就是在同时枚举
6
6
6个变量,每个变量只有选和不选,对应
0
0
0和
1
1
1,那我们可不可以直接枚举从
0
0
0到
63
63
63?这样的话一共
64
64
64中情况,把
0
0
0想象成
000000
000000
000000,
63
63
63想象成
111111
111111
111111,你看,这样的话其实从
0
0
0到
63
63
63,每一个十进制数本质上都对应了六个人的一种选取情况。
那么问题来了,我们如何处理这些情况呢?比如当前进来一个
010100
010100
010100,我们怎么才能很好地把其中的
C
C
C和
E
E
E取出来?这里其实要用到位运算。如果实在理解不了,我们也可以用之前学的十进制转二进制来完成,对于取出来的二进制字符串遍历一遍就可以得到六个人的犯罪情况了。
详情看代码:
def find():
Name = ['A', 'B', 'C', 'D', 'E', 'F']
###########请在此行之后编写程序###########
##切勿在此部分代码中使用input和print语句##
for i in range(2 ** 6) :
num = [0] * 6
for j in range(6) :
if i & (2 ** j) :
num[j] = 1
flag = True
if num[0] + num[1] == 0 :
flag = False
if num[0] + num[3] > 1 :
flag = False
if num[0] + num[4] + num[5] < 2 :
flag = False
if num[1] + num[2] == 1 :
flag = False
if num[2] + num[3] != 1 :
flag = False
if num[3] == 0 and num[4] == 1 :
flag = False
if flag == True :
ret = []
for j in range(6) :
if num[j] :
ret.append(Name[j])
return ret
###########请在此行之前编写程序###########
if __name__ == '__main__':
#此行之后的代码用于测试运行结果,可根据个人需要添加调试代码,包括使用input和print语句
print(find())
T3 阶乘之和
简单题,只需要维护一个 m d l mdl mdl变量,他表示当前的 i ! i! i!,每次循环加一下即可。
def sum_fac(n):
###########请在此行之后编写程序###########
##切勿在此部分代码中使用input和print语句##
mdl, ans = 1, 0
for i in range(1, n + 1) :
mdl *= i
ans += mdl
return ans
###########请在此行之前编写程序###########
if __name__ == '__main__':
#此行之后的代码用于测试运行结果,可根据个人需要添加调试代码,包括使用input和print语句
n=eval(input())
print(sum_fac(n))
T4 二进制数减1
这个题就很好,我用了一下
r
f
i
n
d
rfind
rfind函数,这个是我写博客之后读者分享跟我的,很好用。
我们只需要找到这个二进制右侧开始的第一个
1
1
1,不难发现,这个
1
1
1会变成
0
0
0,这个
1
1
1右侧的
0
0
0都会变成
1
1
1,根据这个模拟一下即可。
有两种特殊情况,第一种是这个二进制是
1000...00
1000...00
1000...00的形式,这样的话开头会有一个前导
0
0
0,只需要判断第一位是不是
0
0
0,删掉即可;第二种情况就是第一种情况里我们删去了第一个
0
0
0,但是
1
1
1做减法之后就剩一个
0
0
0,所以我们需要把这种情况特判出来。
def minus1(x):
###########请在此行之后编写程序###########
##切勿在此部分代码中使用input和print语句##
dic = x.rfind('1')
y = x[ : dic]
#dic + 1
y = y + '0' + '1' * (len(x) - dic - 1)
if len(y) > 1 and y[0] == '0' :
y = y[1 : ]
return y
###########请在此行之前编写程序###########
if __name__ == '__main__':
#此行之后的代码用于测试运行结果,可根据个人需要添加调试代码,包括使用input和print语句
x=input()
print(minus1(x))
T5 矩阵转置
运用嵌套列表,但是难度不大因为该建的都给建好了。
只需要枚举循环的时候赋值即可。
def transpose(A):
###########请在此行之后编写程序###########
##切勿在此部分代码中使用input和print语句##
#构建m×n的全0矩阵
n,m=len(A),len(A[0])#A是n×m的矩阵
AT=[] #A的转置AT是m×n
for i in range(m): #AT有m行(即AT中包含m个列表)
AT.append([0]*n)#AT有n列(即AT中每个列表包含n个数)([0]*n是创建一个包含n个0的列表)
for i in range(n) :
for j in range(m) :
AT[j][i] = A[i][j]
return AT
###########请在此行之前编写程序###########
if __name__ == '__main__':
#此行之后的代码用于测试运行结果,可根据个人需要添加调试代码,包括使用input和print语句
M=eval(input())
print(transpose(M))