Pythontip刷题记录

pythontip 刷题记录

11.给你一个正整数列表 L, 输出L内所有数字的乘积末尾0的个数。(提示:不要直接相乘,数字很多,相乘得到的结果可能会很大)。

不能直接相乘会太大了,分解质因数,去找2和5的个数,取最小值

def solve_it():

	cont2=0
	cont5=0
	for i in L:
    	while i%2 == 0:
        	cont2 += 1
        	i = i//2
    	while i%5 == 0:
        	cont5 += 1
        	i= i//5
	return min(cont2,cont5) #your answer

print(solve_it())  # 答案需要输出

12.给你一个正整数列表 L, 判断列表内所有数字乘积的最后一个非零数字的奇偶性。如果为奇数输出1,偶数则输出0.。

注意看题目里是最后一位非0,

a = 1
for i in L:
	a *= i
while True:
	if a % 10 == 0:
    	a = a // 10
	else:
    	break

if a%2 ==0:
	print(0)
else:
	print(1)

13.给你一个整数a,数出a在二进制表示下1的个数,并输出。

b = bin(a)  # bin函数可以把数字转化为二进制
b = str(b)
s=0
for i in b:
	if i == '1':
    	s +=1
print(s)

15.给定一个字符串a, 将a中的大写字母 转换成小写,其它字符不变,并输出。

例如:a=“aaaaaabbbDDDDD”

则输出:aaaaaabbbddddd

这题就很简单了,全都输出成小写就好了

print(a.lower())

16.银行在打印票据的时候,常常需要将阿拉伯数字表示的人民币金额转换为大写表示,现在请你来完成这样一个程序。

在中文大写方式中,0到10以及100、1000、10000被依次表示为: 零 壹 贰 叁 肆 伍 陆 柒 捌 玖 拾 佰 仟 万

以下的例子示范了阿拉伯数字到人民币大写的转换规则:

1 壹圆

11 壹拾壹圆

111 壹佰壹拾壹圆

101 壹佰零壹圆

-1000 负壹仟圆

1234567 壹佰贰拾叁万肆仟伍佰陆拾柒圆

现在给你一个整数a(|a|<100000000), 请你打印出人民币大写表示.

例如:a=1

则输出:壹圆

这段代码写的很好

dict = {'1':'壹','2':'贰','3':'叁','4':'肆','5':'伍','6':'陆','7':'柒','8':'捌','9':'玖','0':'零'}
dict_liang = {0:'',1:'拾',2:'佰',3:'仟'}
list_wrong = ['零仟','零佰','零拾','零零']
# 4 位 4 位的取就好了
def func(S): # 转换的函数,但如果第一位是0的话末尾还是会有个0,后面会剔除
	ans = ''
	for i in range(len(S) - 1,-1,-1):
    	ans = ans + dict[S[i]] + dict_liang[i]
    	for s_wrong in list_wrong:
        	if s_wrong in ans:
          		ans = ans.replace(s_wrong,'零')
	return ans
flag = 1
#a = -34009
if a < 0:
	flag = -1
	a = abs(a)
ans = ''
s = str(a)
s = s[::-1]

#倒着做符合从个位往高位数的习惯
if len(s) <= 4:
	ans = func(s)
else:
	s1 = s[:4]
	s2 = s[4:]
	ans = func(s2) + '万' + func(s1)
	if '零万' in ans:
    	ans = ans.replace('零万','万')  # fun函数的缺点就是如果你最后一位(反转后的第一位)是0的话,他的0没法在里面去除,所以这里要再去除一下
ans += '圆'
if '零圆' in ans:
	ans = ans.replace('零圆','圆')
if flag == -1:
	ans = '负' + ans
if a == 0:
	ans = '零圆'
print(ans)

17.给你两个正整数a,b, 输出它们公约数的个数。

from math import gcd

c = gcd(a,b)
list1 = []
for i in range(1,c+1):
	if c % i == 0:
    	list1.append(i)

print(len(list1))

18.我们经常遇到的问题是给你两个数,要你求最大公约数和最小公倍数。今天我们反其道而行之,给你两个数a和b,计算出它们分别是哪两个数的最大公约数和最小公倍数。输出这两个数,小的在前,大的在后,以空格隔开。若有多组解,输出它们之和最小的那组。注:所给数据都有解,不用考虑无解的情况。

设两个数为 ac ad (a是最大公约数),那么现在就要找c和d,且c与d互质。
并且c d 最大不能超过 b//a。超过了话那 a*c 和a *d不就超过了 b嘛 ,那他们的最小公因数就不可能是b了。

a=3
b=60
list01 = []
m = max(a, b)
n = min(a, b)
l = m // n  #两个数相等要等于m*n 所以两个数一定都在n到m//n范围内,不小于n是肯定是,如果大于了m//n就证明有个数要小于n也不行
for i in range(1, l + 1):
	if l % i == 0:
    	list01.append(i)
c = list01[len(list01) // 2]   # 取中间两个数是因为他们相加一般都是最小的
d = list01[len(list01) // 2 - 1]
print(d * n, c * n, end='')

19.给你一个字符串a,如果其中包含"LOVE"(love不区分大小写)则输出LOVE,否则输出SINGLE。

c=a.lower().count('love')
if c > 0:
	print("LOVE")
else:
	print('SINGLE')

20.给你个小写英文字符串a和一个非负数b(0<=b<26), 将a中的每个小写字符替换成字母表中比它大b的字母。这里将字母表的z和a相连,如果超过了z就回到了a。

运用ord和chr。ord()函数主要用来返回对应字符的ascii码,chr()主要用来表示ascii码对应的字符他的输入时数字

#a = "cagy" 
#b = 3
list1 = []	
for i in a:
	c = ord(i) + b
	if c >123:
    	c = c % 123 +97
	list1.append(chr(c))
print(''.join(list1))

21.给你一个字符串a和一个正整数n,判断a中是否存在长度为n的回文子串。如果存在,则输出YES,否则输出NO。 回文串的定义:记串str逆序之后的字符串是str1,若str=str1,则称str是回文串,如"abcba".

flag = False
for i in range(len(a)):
	if i + n ==len(a):
    	c = a[i:i+n]
    	if c == c[::-1]:
        	flag = True
        	break

if flag :
	print('YES')
else:
	print('NO')

22.给你两个时间st和et(00:00:00<=st <= et<=23:59:59), 请你给出这两个时间间隔的秒数。 如:st=“00:00:00”, et=“00:00:10”, 则输出10.

s = [int(x) for x in st.split(':')]
e = [int(x) for x in et.split(':')]
sum = 0
sum1 = (e[0] - s[0])*60*60  # 正负这道题我们不用考虑,他是负的就负的好了
sum2 = (e[1] - s[1])*60
sum3 = e[2] - s[2]

sum = sum1+sum2+sum3
print(sum)

23.一年有多少天,这是个大问题,很值得思考。现在给你一个年份year(year为四位数字的字符串,如"2008",“0012”), 你输出这一年的天数。如year=“2013”, 则输出365。

老生常谈了,可以搜一个闰年的定义

year  = int(year)
if year % 4 == 0 and (year % 100 != 0 or year % 400 ==0):
	print(366)
else :
	print(365)

24.下过象棋的人都知道,马只能走’日’字形(包括旋转90°的日),现在想象一下,给你一个n行m列网格棋盘, 棋盘的左下角有一匹马,请你计算至少需要几步可以将它移动到棋盘的右上角,若无法走到,则输出-1. 如n=1,m=2,则至少需要1步;若n=1,m=3,则输出-1。

# 列出x和y方向所有可能的走法 之后用zip 方便
dx = [1, 2, 2, 1, -1, -2, -2, -1]
dy = [-2, -1, 1, 2, 2, 1, -1, -2]
# 创建一个嵌套的列表,用来存储整个棋盘所有的点
# 类似于数组
# 列表表达式快速生成的,也可以用常规方法生成
# 这里注意一下:4*5的棋盘,代表有5*6个点
vis = [([0] * (m + 1)) for i in range(n + 1)]
# 创建一个列表,用来存储基于当前点位,所有等待访问的点的横坐标和纵坐标,以及本次走过的步长
# 因为有三个数据,所以列表里面嵌套一个元组
# 初始化都为0,代表从坐标轴原点开始 走
q = [(0,0,0)]
vis[0][0] = 1 #从原点开始,表示我们走过了

# 只要有没有访问过的点并且能到达,就执行循环
while q:  # 因为q循环一次会弹出一个、
	temp = q.pop(0)
	# 判断是否到达终点,如果到达终点,则直接输出步长,代表走了多少步
	if temp[0] == n and temp[1] == m:
    	print(temp[2])
    	break
	# zip()函数:把两个列表变成一个列表+元组的形式
	# 遍历所有的走法
	for x,y in zip(dx,dy):
    	# 这里,curx和cury分别代表了即将要走的点
    	# 通过for循环,能把当前位置所有能走的点都遍历到
    	curx = temp[0] + x
    	cury = temp[1] + y
    	# curstep放在这里,只有成功走了一个点,这个变量的值才会增加1
    	curstep = temp[2] + 1
    	if 0<= curx <= n and 0<= cury <= m and vis[curx][cury] != 1:
        	# 未超出边界,或者未走过这个点,则标记为1,代表这个点走了
        	vis[curx][cury] == 1
        	# 把这个点和步长加入到q中,提供给下一次while循环使用,下一次循环就会从这个点开始往下走
        	q.append((curx,cury,curstep))
else:
	print(-1)

25.给你一个时间t(t是一个字典,共有六个字符串key(year,month,day,hour,minute,second),值为每个值为数字组成的字符串, 如t={‘year’:‘2013’,‘month’:‘9’,‘day’:‘30’,‘hour’:‘16’,‘minute’:‘45’,‘second’:‘2’} 请将其按照以下格式输出, 格式:XXXX-XX-XX XX:XX:XX。如上例应该输出: 2013-09-30 16:45:02。

利用datetime库

import datetime
print(datetime.datetime(**{k:int(t[k]) for k in t.keys()}).strftime("%Y-%m-%d %H:%M:%S"))

26.给你一个整数组成的列表L,按照下列条件输出: 若L是升序排列的,则输出"UP"; 若L是降序排列的,则输出"DOWN"; 若L无序,则输出"WRONG"。

m1,m2 = L.copy(),L.copy()
m1.sort()
m2.sort(reverse = True)
if m1 == L:
	print('UP')
elif L == m2:
	print('DOWN')
else:
	print('WRONG')

27.一个环形的公路上有n个加油站,编号为0,1,2,…n-1, 每个加油站加油都有一个上限,保存在列表limit中,即limit[i]为第i个加油站加油的上限, 而从第i个加油站开车开到第(i+1)%n个加油站需要cost[i]升油,cost为一个列表。 现在有一辆开始时没有油的车,要从一个加油站出发绕这个公路跑一圈回到起点。 给你整数n,列表limit和列表cost,你来判断能否完成任务。 如果能够完成任务,输出起始的加油站编号,如果有多个,输出编号最小的。 如果不能完成任务,输出-1。

gas_station = []  # 能完成任务的加油站编号列表
for i in range(n):  # 从第0个加油站作为起点开始算
	gas_total = 0  # 汽车的油量
	station_num = 0  # 经过加油站的个数

	for j in range(i,n+i):
    	if j >=n:
        	j = j-n
    	gas_total += limit[j] # 加油
    	if gas_total >= cost[j]:
        	station_num +=1
        	gas_total = gas_total-cost[j]
    	else:
        	break # 不够就直接跳出了
    	if station_num == n:
        	gas_station.append(i)

if gas_station != []:
	print(min(gas_station))
else:
	print(-1)

28.给你一个整数列表L,判断L中是否存在相同的数字, 若存在,输出YES,否则输出NO。

flag = 0
for i in range(len(L)):
	for j in range(i+1,len(L)):
    	if L[i] == L[j]:
        	flag = 1
        	break

if flag:
	print('YES')
else :
	print('NO') 

29.给你三个整数a,b,c, 判断能否以它们为三个边长构成三角形。 若能,输出YES,否则输出NO。

list = [a,b,c]
list.sort()
if list[0] + list[1] >list[2]:
	print('YES')
else:
	print('NO')

30.一道水题哈哈哈就不给了

31.十一假期,小P出去爬山,爬山的过程中每隔10米他都会记录当前点的海拔高度(以一个浮点数表示), 这些值序列保存在一个由浮点数组成的列表h中。回到家中,小P想研究一下自己经过了几个山峰,请你帮他计算一下,输出结果。 例如:h=[0.9,1.2,1.22,1.1,1.6,0.99], 将这些高度顺序连线,会发现有两个山峰,故输出一个2(序列两端不算山峰)

h_jian=[]
for i in range(len(h)-1):
	h_jian.append(h[i+1]-h[i])
sum = 0
for i in range(len(h_jian)-1):
	if h_jian[i] > 0 and h_jian[i + 1] <0:
    	sum += 1
print(sum)

32.给以一个三角形的三边长a,b和c(边长是浮点数),请你判断三角形的形状。 若是锐角三角形,输出R, 若是直角三角形,输出Z, 若是钝角三角形,输出D, 若三边长不能构成三角形,输出W.

list1 = [a,b,c]
list1.sort()
a = list1[0];b = list1[1];c = list1[2];
if a + b < c:
	print('W')
elif (a*a+b*b-c*c)/2*a*b == 0 :
	print('Z')
elif (a*a+b*b-c*c)/2*a*b < 0:
	print('D')
else :
	print('R')

33.给你两个正整数a(0 < a < 100000)和n(0 <= n <=100000000000),计算(a^n) % 20132013并输出结果

直接a**n%20132013的话时间复杂度太高了,用pow函数

print(pow(a,n,20132013))

34.生活在当代社会,我们要记住很多密码,银行卡,qq,人人,微博,邮箱等等。小P经过一番思索之后,发明了下面这种生成密码方法:给定两个正整数a和b, 利用a / b我们会得到一个长度无限的小数(若a / b不是无限小数,比如1/2=0.5,我们认为0.5是0.5000000…,同样将其看做无限长的小数),小P将该小数点后第x位到第y位的数字当做密码,这样,无论密码有多长,小P只要记住a,b,x,y四个数字就可以了,牢记密码再也不是那么困难的事情了。现在告诉你a,b,x,y(0 < a,b <= 20132013, 0 < x <= y < 100000000000),请你输出密码。例如:a = 1, b = 2, x = 1, y = 4, 则 a / b = 0.5000000…, 输出小数点后第1到4位数字,即5000

首先有个余数定理,(ab)%c=(a%c)(b%c)%c,其实比较好理解的是(ab)%c=(a%c)(b%c),这就一分配律,这个式子对于很多数字都是成立的,但是也有特殊情况,比如,23,19除以5的余数分别是3和4,但2319对5取余不是12啊,还得再做一次取余,即(ab)%c=(a%c)*(b%c)%c。

转化一下,a/b的小数点后第x到y位,将结果的小数点后移(x-1)位,即为小数点后第1位到(y-x+1)位
也就是关注(a10^(x-1))/b的小数点后的结果,忽略小数点前的结果,即对b取余后的结果除以b的结果
(a
10^(x-1))%b = ((a%b)*(10^(x-1)%b))%b,这个数字肯定小于b

想想,如果40 /26,你想拿到小数点后的第一位,是不是要40%26后,乘以10 = 140,然后140再//26, 你想想你做除法的时候是怎么做的。想想除法的过程

r=''
a = (a%b*pow(10,x-1,b))%b
for i in range(x,y+1):
	a = (a % b) *10
	r += str(a // b)
print(r)

35 .给你一个整数list L, 如 L=[2,-3,3,50], 求L的一个连续子序列,使其和最大,输出最大子序列的和。 例如,对于L=[2,-3,3,50], 输出53(分析:很明显,该列表最大连续子序列为[3,50]).

max = L[0]
for i in range(len(L)+1):
	for j in range(i,len(L)+1):
    	s = sum(L[i:j])
    	if s > max:
        	max = s
print(max) 

36.给你一个整数list L, 如 L=[2,-3,3,50], 求L的一个非连续子序列,使其和最大,输出最大子序列的和。 这里非连续子序列的定义是,子序列中任意相邻的两个数在原序列里都不相邻。 例如,对于L=[2,-3,3,50], 输出52(分析:很明显,该列表最大非连续子序列为[2,50]).

# L_max用来存放L数组中对应位置前N项中的最大子序列的和
L_max = [0] * len(L)
if len(L) <= 2:
	print(max(L))
else:
	L_max[0] = L[0]
	L_max[1] = max(L[0], L[1])
	for i in range(2, len(L)):
    	# 对L_max[i]的赋值为,以下三项中最大的一项:L_max[i - 1], L[i] + L_max[i - 2], L[i]
    	L_max[i] = max(L_max[i - 1], L[i] + L_max[i - 2], L[i])
	print(L_max[-1])

37.给你直角三角形的两个直角边的边长a,b,请你求出其斜边边长,结果保留小数点后三位小数。 如a=3, b =4, 则输出5.000。

import math
res = math.sqrt(a**2+b**2)
print('%.3f'%res)

38.给你一个字符串列表L,请用一行代码将列表所有元素拼接成一个字符串并输出。 如L=[‘abc’,‘d’,‘efg’], 则输出abcdefg。

print(''.join(L))

39.给你一个字符串列表L,用一行代码顺序输出L中的元素,元素之间以一个空格隔开,注意行尾不要有空格,输出单独占一行。 如L=[‘abc’,‘d’,‘efg’], 则输出abc d efg。

print(' '.join(L))

40.给你两个整数a和b(-10000<a,b<10000),请你判断是否存在两个整数,他们的和为a,乘积为b。若存在,输出Yes,否则输出No

例如:a=9,b=15, 此时不存在两个整数满足上述条件,所以应该输出No。

flag = "No"
if b == 0:
	flag = "yes"
else:
	for x in range(-10000, abs(a)+1): #x最大值不会超过a的绝对值
    	if b == x * (a - x):
        	flag = "Yes"
        	break
print(flag)

41.Py从小喜欢奇特的东西,而且天生对数字特别敏感,一次偶然的机会,他发现了一个有趣的四位数2992, 这个数,它的十进制数表示,其四位数字之和为2+9+9+2=22,它的十六进制数BB0,其四位数字之和也为22, 同时它的十二进制数表示1894,其四位数字之和也为22,啊哈,真是巧啊。 Py非常喜欢这种四位数,由于他的发现,所以这里我们命名其为Py数。 现在给你一个十进制4位数n,你来判断n是不是Py数,若是,则输出Yes,否则输出No。 如n=2992,则输出Yes; n = 9999,则输出No。

def f(n,m):
	a=[]
	while(n):
    	a.append(int(n%m))
    	n = n//m
	return a

n_16 = f(n,16)
n_12 = f(n,12)

n = str(n)
sum1 = 0
for i in n:
	sum1 += int(i)

if sum1 == sum(n_16) == sum(n_12):
	print('Yes')
else :
	print('No')

42.把一个偶数拆成两个不同素数的和,有几种拆法呢? 现在来考虑考虑这个问题,给你一个不超过10000的正的偶数n, 计算将该数拆成两个不同的素数之和的方法数,并输出。 如n=10,可以拆成3+7,只有这一种方法,因此输出1.

sushu=[]
for i in range(2,10001):  # 1不算 从2 开始
	for j in range(2,int(i/2)):   #到i/2就可以,减少时间复杂度
    	if i % j == 0:   #判断是否是素数
        	break
	else :
    	sushu.append(i)
#n = 4
sum1 = 0
for i in sushu:
	for j in sushu:
    	if n == i+j and i != j:
        	sum1 += 1
print(sum1//2)

43斐波那契数列为1,1,2,3,5,8…。数列从第三项起满足,该项的数是其前面两个数之和。现在给你一个正整数n(n < 10000), 请你求出第n个斐波那契数取模20132013的值(斐波那契数列的编号从1开始)

a=[1,1]
for i in range(2,n):
	a.append(a[i-2] + a[i-1])
print(a[n-1] %20132013)

44.有一楼梯共n级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第n级,共有多少种走法? 现在给你一个正整数n

第n个台阶走法数等于n-1 和 n-2级的走法数之和

L = [0] * n
L[0],L[1] = 1,1
for i in range(2,n):
	L[i] = L[i-1] + L[i-2]
print(L[n-1])

45.有一组砝码,重量互不相等,分别为m1、m2、m3……mn;它们可取的最大数量分别为x1、x2、x3……xn。 现要用这些砝码去称物体的重量,问能称出多少种不同的重量。 现在给你两个正整数列表w和n, 列表w中的第i个元素w[i]表示第i个砝码的重量,列表n的第 i个元素n[i]表示砝码i的最大数量。i从0开始,请你输出不同重量的种数。 如:w=[1,2], n=[2,1], 则输出5(分析:共有五种重量:0,1,2,3,4)

#w = [1, 2, 3];n = [12, 5, 8]
w_count = []
for i in range(len(w)):
	for _ in range(n[i]):
    	w_count.append(w[i])  # 先把砝码给展开看
s=[]
for i in range(len(w_count)):
	a = w_count[i]         
	if a not in s:
    	s.append(a)
	for j in range(i+1,len(w_count)):  # 展开后是这样,先看第一个有没有,没有的话就加入,然后看第一个加第二个,第一个+第二个+第三个... 第二个+第三个+...
    	a += w_count[j]
    	if a not in s:
        	s.append(a)
s.append(0) # 0的话每个都可以测的
s.sort()  # 看的舒服一点哈哈
print(len(s))

46.有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法, 一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。 现在给出初始的两堆石子的数目a和b,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。 如果你是胜者,输出Win,否则输出Loose。 例如,a=3,b=1, 则输出Win(你先在a中取一个,此时a=2,b=1,此时无论对方怎么取,你都能将所有石子都拿走).

威佐夫博弈,套入公式定理,会用就行了

n = abs(a - b)
m = min(a, b)
if m == int(n*(pow(5, 0.5)+1)//2):
	print('Loose')
else:
	print('Win')

47.还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考以下的图形: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 … 先在给你一个正整数n,请你输出杨辉三角的前n层 注意:层数从1开始计数,每层数字之间用一个空格隔开,行尾不要有空格。 如n=2,则输出: 1 1 1

m=[]
for i in range(n):
	m.append([])
	for j in range(i+1):
    	m[i].append(0)  # 先给他一个数
    	if j == 0 or j == i :
        	m[i][j] = str(1)
    	else:
        	temp = int(m[i-1][j-1]) + int(m[i-1][j])
        	m[i][j] = str(temp)

for i in range(len(m)):
	for j in range(len(m[i])):
    	if j == len(m[i]) -1:
        	print(m[i][j])
    	else:
        	print(m[i][j],end = ' ')

48.有一组砝码,重量互不相等,分别为m1、m2、m3……mn;每种砝码的数量有无限个。 现要用这些砝码去称物体的重量,给你一个重量n,请你判断有给定的砝码能否称出重量n。 现在给你一个正整数列表w和一个正整数n,列表w中的第i个元素w[i]表示第i种砝码的重量, n表示要你判断的重量。如果给定砝码能称出重量n,输出Yes,否则输出No。 例如,w=[2,5,11], n=9,则输出Yes(取两个2,一个5)。

w.sort()
w = w[::-1]
for i in range(len(w)):
	n = n % w[i]
	if n == 0:
    	print('Yes')
    	break
else:
	print('No')

49.给你一个十进制数a,将它转换成b进制数,如果b>10,用大写字母表示(10用A表示,等等) a为32位整数,2 <= b <= 16 如a=3,b = 2, 则输出11

a = 31;b = 16
def f(n,m):
	a=[]
	while(n):
    	a.append(int(n%m))
    	n = n//m
	return a
def zh(a,b):
	list1 = f(a,b)
	s = ''
	l = ['A','B','C','D','E','F']
	for i in list1:
    	if i < 10:
        	s += str(i)
    	else:
        	s += l[i-10]
	return s[::-1]

if a > 0:
	print(zh(a,b))
elif a == 0:
	print(0)
else :
	print('-' + zh(-a,b))

50.Py不但是编程大牛,而且是运动健将。比如说扔铅球,1000m,现在Py参加校园扔铅球比赛, 给你Py的身高a(双精度数),球落地点与Py头部的连线与水平线的夹角 b(弧度), 要你编写一个程序计算Py扔铅球的水平距离。 a,b都是浮点数,注意b是弧度,其中, 140 < a < 200, 0 < b < 1.5. 输出你求出的水平距离,保留到小数点后三位。 如,a = 165.5, b=1.1, 则输出84.234

import math
c = a / (math.tan(b))
print('%.3f' % c)

51.给你一个list L, 如 L=[2,8,3,50], 对L进行降序排序并输出, 如样例L的结果为[50,8,3,2]

print(sorted(L,reverse = True))

52. 6 的因子有 1, 2, 3 和 6, 它们的平方和是 1 + 4 + 9 + 36 = 50. 如果 f(N) 代表正整数 N 所有因子的平方和, 那么 f(6) = 50. 现在令 F 代表 f 的求和函数, 亦即 F(N) = f(1) + f(2) + … + f(N), 显然 F 一开始的 6 个值是: 1, 6, 16, 37, 63 和 113. 那么对于任意给定的整数 N (1 <= N <= 10^8), 输出 F(N) 的值.

这题最重要的就是要考虑到时间复杂度的问题,正常来说像这样是最常规的

def f(n):
	list1 = []
	for i in range(1,n+1):
    	if n % i == 0:
        	list1.append(i)
	sum = 0
	for i in range(len(list1)):
    	sum += list1[i]**2
	return sum

def F(n):
	sum = 0
	for i in range(1,n+1):
    	sum += f(i)
	return sum

print(F(6))

但时间复杂度是n^2,太高了,想办法降下来

考虑到首先思路当n=100的时候,1的倍数有100个,所以1是这100个数的因子,所以要平方100次,2的倍数是100/2=50个,以此类推,直到50的倍数有 两个,50以上全部都是一个
想想那如果不算100的话,是不是50的平方只要加一次,其他的类推

s = (N * (N + 1) * (2*N + 1)) // 6
ls = ( i * i * (N // i - 1) for i in range(1, N//2+1)) 
s += sum(ls)
print(s)

53.如果我们定义 (n, m) 是一个安排(其中 1 < m < n), 而如果 C(m,2)/C(n,2) = 1/2, 它就是神的安排. 现在的问题是, 给你一个不大于 10^9 的正整数 N, 有多少组神的安排 (n, m) 满足 n <= N 呢?

佩尔方程

'''	
根据题意列出方程 2*m^2-2*m=n^2-n,转换为佩尔方程形式:
(2*n-1)^2-2*(2*m-1)^2=-1。
记x=2n-1,y=2m-1,原方程即为:x^2-2*y^2=-1
先计算x^2-2*y^2=1的基本解,(3,2)为基本解,
得到 x,y的迭代公式:
x=3x0+4y0,y=2x0+3y0
最小的(x0,y0)为(1,1),要求n>m>1,且n和m需要为整数
分析发现x和y一直为奇数,所以不再需要判断n和m是否为整数
'''
x = 1
y = 1
c = -1  # 计数,初始值设为-1,N=1时,(x,y)=(1,1),c=0
while x <= 2 * N - 1:
	c += 1
	x, y = 3 * x + 4 * y, 2 * x + 3 * y
print(c)

54.记得一副有趣的对联: “雾锁山头山锁雾, 天连水尾水连天”, 上联和下联都是回文的. 当然类似的还有: “上海自来水水来自海上, 山西悬空寺寺空悬西山”. 回文是什么意思? 就是把内容反过来读也是和原来一样的, 譬如 abccba, xyzyx, 这些都是回文的. 然而我们更感兴趣的是在一个英文字符串 L 中, 怎么找出最长的回文子串. 例如 L = “caayyhheehhbbbhhjhhyyaac”, 那么它最长的回文子串是 “hhbbbhh”. 这个任务看似简单, 但是如果我告诉你 L 的长度可能会接近 10^4, 问题似乎就变麻烦了. 不管怎么说, 加油吧骚年.

manacher算法

def init1(s):
	S = "^#"
	for i in range(0,len(s)):
    	S = S + s[i] + "#"
	S = S + "$"
	return S    # 前后加两个不同的符号是为了后面判断while的时候超出范围
   

def solution(s):
	s = init1(s)
	P = [0 for i in range(0,len(s))]
	M=0;R=0
	for i in range(1,len(s)-1):
    	j = M*2 - i
    	if R > i:
        	if R - i > P[j]:
            	P[i] = P[j]
            
        	else :
            	P[i] = R - i
    	else :
        	P[i] = 0
    	while s[i + P[i] + 1] == s[i - P[i] -1]:
        	P[i] = P[i] + 1
    
    	if i + P[i] > R:
        	R = i + P[i]
        	M = i

	Center = 0
	maxl = 0
	for i in range(1,len(s)-1):
    	if P[i] >= maxl:
        	maxl = P[i]
        	Center = i
    	start = Center - maxl+1
    	end = Center + maxl

	return s[start:end:2]

print(solution(L))

57.不知道大家的童年有没有过和我相似的经历。我记得小时候经常买干脆面,不为别的,只是因为里面有一张人物卡片。 其实有很多这样的活动都有一个相同的模式:N 种人物卡片,每次买一包干脆面随机得到一张。当你集齐这 N 种人物时,就会有相应的奖励。 那时候还不懂怎么计算概率,白白给人家送了好多钱,吃了好多干脆面。 现在的任务是,给你一个正整数 N (1 <= N <= 10^4),请你帮我从期望的角度计算平均需要买多少包干脆面才能集齐这 N 种人物。 提醒:由于结果可能不是整数,所以结果只保留到小数点后两位。

1种卡片,怎么买都可以买到,期望就是 1
2种卡片,拿到第1种以后,拿到第2种的概率就是 1/2, 理论上还需要买2包。期望和 = 3/3 + 2/1
3种卡片, 拿到第1种以后,拿到第2种的概率就是2/3, 理论上需要买 3/2 包,再拿到第3种的概率就是 1/3 ,理论上需要买 3/1 包。 期望和 = 3/3 + 3/2 + 3/1

sum = 0
for i in range(1,N+1):
	sum += N/i
print('%.2f'% sum)

58.小Py要吃西瓜,想知道切了n刀后,最多能切出多少块?请你们帮助下小Py. 给你一个正整数n(0 < n < 10^3),你输出一个数字,代表最多能切多少块。 如n=1, 输出2。

这个问题的本质是n个平面最多可以把空间划分成多少块.我们来看如下三个问题:

  1. n个点最多可以把一条直线划分成多少段,通项公式记为A(n)。 2) n条直线最多可以把平面划分多成个区域,通项公式记为B(n)。 3) n个平面最多可以把空间划分多少块,通项公式记为C(n)。

第一个问题,很简单,A(n) = n+1

第二个问题,假设平面上已有n条直线它们把平面划分成最多的区域,那么第n+1条直线下去的时候,为了保证获得最多的区域,那么要求这条直线和之前的n条直线都相交,并且新产生的交点不和之前的交点重合.显然第n+1条直线和之前的n条直线产生n个交点,这n个交点把第n+1条直线划分成A(n)段,每一段都将原来的区域一分为二,于是B(n + 1) = B(n) + A(n),将B(1) = 2,A(n) = n + 1带入很容易求得B(n) = [n(n + 1) / 2] + 1

第三个问题,同理考察第n+1个平面下去多增加了多少块.前面的n个平面都和第n+1个平面相交,在第n+1个平面上留下n条交线,这n条交线最多将第n+1个平面划分成B(n)个区域,每个区域都将原来的块一分为二,于是C(n+1) = C(n) + B(n),将C(1) = 2,B(n) = [n(n + 1) / 2] + 1带入可以求得C(n) = [(n^3 + 5n) / 6] + 1

print(int((n**3+5*n+6)/6))

59.M个人围成一圈,每分钟相邻的两个人可以交换位置(只能有一对交换)。 现在给你一个正整数n(0 < n < 1000),求使n个人的顺序颠倒(即每个人左边相邻的人换到右边,右边相邻的人换到左边)所需的最少时间(分钟数)。 如:n=4, 输出2.

根据奇偶来一分为二,因为这是成环的,不需要把 12345 转化成 54321, 变成 32154 就可以了。
然后再讨论一下,把一个数组倒过来,需要多少步,这实际上还是很好算的。自己可以推导一下。
我给一个 递推公式: f[n] = f[n-1] + n-1

nums = [0, 0, 1, 3]

for i in range(4, 1000):
	nums.append(nums[i-1] + i-1)

print(nums[n//2]+nums[n//2] if n % 2 == 0 else nums[n//2] + nums[n//2+1])

60.给你一个正整数list L, 如 L=[2,8,3,50], 求列表中所有数的最小公倍数(不用考虑溢出问题)。 如L=[3,5,10], 则输出30

最大公约数*最小公倍数 = 两个数的乘积

from math import gcd
ans = 1
for num in L:
	gc = gcd(ans, num)
	ans = (ans * num) // gc

print(ans)

61.现在有一堆木棒,告诉你它们的长度,判断能否用这些木棒拼接成正方形。 注意:所有的木棒都要用上,且不能截断。 给你一个正整数list L, 如 L=[1,1,1,1], L中的每个数字代表一个木棒的长度,如果这些 木棒能够拼成一个正方形,输出Yes,否则输出No。 如L=[1,1,1,1],则输出Yes;L=[1,1,1],则输出No。 注:数据已于2014-03-11加强,之前通过的代码可能无法再次通过

如果木棒总长度不是4的倍数,那么肯定不能组合成一个正方形。
如果我们用排列组合的方式,那就相当于是 4^n 次方,肯定超时,就不多想了。
然后我再想,先一分为二,再一分为二。 初步估计了一下时间复杂度,放弃了。
正确的办法:

  • 将所有木棒根据长度从大到小排序。
  • 得到所有木棒的长度总和,判断能否构成四边形以及四边的长度。
  • 再依次将木棒放到四边剩余长度最大的边。
  • 循环操作第3步,直到所有木棒全部放入四边。
  • 最后判断四边是否全部为0。

虽然不知道为啥可以这样,但是代码通过了。我还是给出我的一个思考,感觉没啥问题。
假设我们现在手里拿了 1 根木棒,并且只能放入剩余长度最大的边,其他边放不下这根木棍,那就只能放入剩余长度最大的边了。
如果有 n 个边都可以放,并且这 n 个边剩余长度都一样,那就随便放1个边都可以。
如果现在有 n 个边都可以放,但是 n 个边的 剩余长度都不一样,怎么办?
假设现在有木棒 a > b。 2个边 分别为 A>B。
把 a 放入 A 中,那么A就变成了 A-a。
把 a 放入 B 中,那么B就变成了 B-a
因为 A>B, 所以 A-a > B-a 。
那么 b < A-a 的可能就比 b < B-a 的可能要高,这样我们就可以把更多的木棒加入4边中。
而我们的目的就是尽可能的把所以木棒放入到4个边中。

sum_L = sum(L)
if sum_L%4  or not sum_L:
	print("No")
else:
	lst = [sum_L//4 for i in range(4)]
	L.sort()
	while L:        
    	lst[3] -= L.pop()
    	lst.sort()
	if not min(lst):
    	print("Yes")
	else:
    	print("No")

62.给你两个整数a和b(0 < a,b < 1000),按笔算的格式输出a乘以b(a是被乘数,b是乘数)的运算过程, 最后再输出一行 “********************”(二十个星号)。 乘号用小写字母“x”表示,每行末尾不能有多余的空格

def solve_it(a,b):
	print('%8d' % a)
	print('x%7d' % b)
	print('--------')
	if b//100:
    	print('%8d' % (a * (b % 100)))
    	print('%7d' % (a * (b // 10%10))+' ')
    	print('%6d'% (a * (b // 100))+'  ' )
	elif b//10:
    	print('%8d' % (a * (b % 10)))
    	print('%7d' % (a * (b // 10)) + ' ')
	else:
    	print('%8d' % (a * b ))
    	print('*' * 20)
    	return
	print('--------')
	print('%8d'%(a*b))
	print('*' * 20)
solve_it(a,b)

63.桌子上有一堆数量不超过20的果子,每个果子的重量都是不超过20的正整数,全部记录在列表 L 里面。小明和小红决定平分它们,但是由于他们都太自私,没有人愿意对方比自己分得的总重量更多。而果子又不能切开,所以最后他们商量好的平分方案是这样的:他们可以把某些果子扔掉,再将剩下的果子平分,请你求出在这种方案下他们每人最多可以分得的糖果重量。

贪心算法,但是贪心算法只能适用于大多数情况,会有少数情况得不到最优解

def solve_it(l):
	# 排序
	l.sort()
	# 当最大值大于和的一半,则去除最大元素
	while l[-1] > sum(l) / 2:
    	l.remove(l[-1])
    	if len(l) >= 3:
       		continue
    	# 当列表长度小于3就作个判断即可解决问题
    	else:
        	return l[0] if len(l) == 2 and l[0] == l[1] else 0
	# 将处理好的新列表拷贝,为后面贪心算法做准备
	L = l.copy()
	# 若列表和为奇数,则去除一个最小奇数,使和为偶数进行平分
	if sum(l) % 2 != 0:
    	for i in l:
    		    if i % 2 != 0:
            	l.remove(i)
            	break
	# 记录列表和的一半,并把最大值赋给临时变量
	side = sum(l) // 2
	tmp = l.pop()
	# 循环查找 side - tmp 是否在列表里
	for i in range(len(l)):
    	# 找到,则返回side
    	if side - tmp in l[i+1:] or side - tmp == 0:
        	return side
    	# 找不到,贪心算法,去除一个最小值,递归调用
    	elif tmp + l[i] > side:
        	return solve_it(L[1:])
    	# 循环找
    	else:
        	tmp += l[i]
print(solve_it(L))

64.互联网上的每台计算机都有一个IP,合法的IP格式为:A.B.C.D。 其中A、B、C、D均为位于[0, 255]中的整数。为了简单起见,我们规定这四个整数中不允许有前导零存在,如001这种情况。 现在给你一个字符串s(s不含空白符),请你判断s是不是合法IP,若是,输出Yes,否则输出No. 如:s=“202.115.32.24”, 则输出Yes; s=“a.11.11.11”, 则输出No.

import re
if re.findall('[1-2]?\d?\d\.[1-2]?\d?\d\.[1-2]?\d?\d\.[1-2]?\d?\d', s) == [s]:  #? 是出现一次或者0次
	print('Yes')
else:
	print('No')

65.在RSA密码体系中,欧几里得算法是加密或解密运算的重要组成部分。它的基本运算过程就是解 (x*a) % n = 1 这种方程。 其中,x,a,n皆为正整数。现在给你a和n的值(1 < a,n < 140000000),请你求出最小的满足方程的正整数解x(保证有解). 如:a = 1001, n = 3837,则输出23。

由公式我们可以 知道(x*a) % n = 1,也就是说((x%n) * (a%n)) % n = 1,还有主要的x a = kn + 1,而我们的任务就是去找k的值,到这里就不难了,就是用循环的方式去找k;

但是有一个要注意的就是a的值,如果直接使用的话,会导致超时,由于我们推出的第一个公式,我们可以用a = a % n
a = a % n
k = 0
while True:
if (kn+1) % a == 0:
print(int((k
n+1)/a))
break
else:
k += 1

67.什么叫自复制数呢?我们看看下面的例子: 625×625=390625 376×376=141376 9376×9376=87909376 90625×90625=8212890625 如果一个数的平方末尾还是这个数本身,那么它就是自复制数。 现在告诉你长度为101位的自复制数只有一个,你能把它找出来吗?请输出这个101位的自复制数。

a=7109376

for i in range(8,102):
	a=str(int(a)**5)[-i:]
	#print(a)
	if len(str(a))==101:
    	print(a)

规律是一个n位的自复制数的五次方的负n+1位是新的自复制数的第一位,比如5**5=3125,25也是一个自复制数

68.N的阶乘定义为:N!=N×(N-1)×……×2×1 请编写一个程序,输出N的阶乘的十进制表示中从最末一个非0位开始自低位向高位数的第K位。 现在给你N和K(0<=N<=10000,1<=K<=5),请你输出要求的数字(保证存在)。 例如:N=5,K=2,则输出1 note:(5!=120); N=8,K=3,结果为0 note:(8!=40320)

import math
#N = 777
#K=5
y = math.factorial(N)
while y % 10 == 0:
	y = y//10
print(str(y)[-K])

69.若一个数(首位不为0)从左到右读与从右到左读都是一样,这个数就叫做回文数,例如12521就是一个回文数。 给定一个正整数,把它的每一个位上的数字倒过来排列组成一个新数,然后与原数相加,如果是回文数则停止,如果不是,则重复这个操作,直到和为回文数为止。给定的数本身不为回文数。 例如:87则有: STEP1: 87+78=165 STEP2: 165+561=726 STEP3: 726+627=1353 STEP4: 1353+3531=4884 现在给你一个正整数M(12 <= M <= 100),输出最少经过几步可以得到回文数。如果在8步以内(含8步)不可能得到回文数,则输出0。 例如:M=87,则输出4.

def is_huiwen(x):
	if str(x) == str(x)[::-1]:
    	return 1
	else:
    	return 0
def jiadaoshu(x):
	return x+int(str(x)[::-1])

#M = 87
count = 0
while not is_huiwen(M):
	M = jiadaoshu(M)
	count +=1
if count > 8 :
	print(0)
else:
	print(count)

70.设有n个正整数,将他们连接成一排,组成一个最大的多位整数. 例如:3个整数13,312,343,连成的最大整数为:34331213 又如:4个整数7,13,4,246连接成的最大整数为7424613 现在给你一个正整数列表L,请你输出用这些正整数能够拼接成的最大整数。 note:测试数据已于2014年11月13日更新,以前通过的代码不一定能够再次通过。

Python cmp_to_key用法,排序的规则不单单是数的大小了

from functools import cmp_to_key
L = list(map(str, L))
def cmp_decline(x, y):
	if int(x + y) < int(y + x):
    	return 1
	else:
    	return -1
L.sort(key=cmp_to_key(cmp_decline))
print(''.join(L))

71.又是回文数!但这次有所不同了。 给定一个N进制正整数,把它的各位数字上数字倒过来排列组成一个新数,然后与原数相加,如果是回文数则停止,如果不是,则重复这个操作,直到和为回文数为止。 如果N超过10,使用英文字母来表示那些大于9的数码。例如对16进制数来说,用A表示10,用B表示11,用C表示12,用D表示13,用E表示14,用F表示15。 例如:10进制87则有: STEP1: 87+78=165 STEP2: 165+561=726 STEP3: 726+627=1353 STEP4: 1353+3531=4884 给你一个正整数N(2<=N<=16)和字符串M(“1”<=M<=“30000”(10进制)),表示M是N进制数,输出最少经过几步可以得到回文数。 如果在30步以内(含30步)不可能得到回文数,则输出0。输入的数保证不为回文数。 如N=10, M=“87”, 则输出4.注意:M是以字符串的形式给定的。

def ten_to_N(N,M):
	M = int(M)
	res = ''
	d = {10:'A',11:'B',12:'C',13:'D',14:'E',15:'F'}
	while M:
    	temp = M % N
    	if temp in d:
        	temp = d[temp]
    	res += str(temp)
    	M = M//N
	return res

#N进制转化为10进制
def N_to_ten(N,M):
	res = 0
	d = {'A':10,'B':11,'C':12,'D':13,'E':14,'F':15}
	count = len(M) - 1
	for each in M:
    	if each in d:
        	each = d[each]
    	res += pow(N,count) * int(each)
    	count -= 1
	return res
#回文数   
def Hui(n):
	t = str(n)
	if t == t[::-1]:
    	return 1
	return 0

count = 30      #最多30次
flag = 0
while count:
	if Hui(M):  #如果是回文数,标志flag = 1
    	flag = 1
    	break
	else:
    	temp = M
    	sum1 = N_to_ten(N,M)    #本身转化为10进制
    	sum2 = N_to_ten(N,M[::-1])  #倒过来的数转化为10进制
    	M = ten_to_N(N,str(sum1 + sum2)) #10进制相加后转回N进制
    	count -= 1      #次数减一
print(30 - count) if flag else print(0)

72.球赛门票的售票处规定每位购票者限购一张门票,且每张门票售价50元。购票者中有m位手持50元钱币,另有n人手持100元。假设售票处开始售票时无零钱。问这m+n人有几种排队方式可使售票处不致出现找不出钱的局面。 对给定的m,n(0<=m,n<=5000),计算出排队方式总数。

def solve_it(m,n):
	if n > m:
    	return 0
	else:
    	row = [1 for _ in range(m)]
    	column = [0 for _ in range(n)]
    	# 不断进行值的覆盖
    	for i in range(n):
        	for j in range(i,m):
            	row[j] += column[i]
            	column[i] = row[j]
        	# print(row, column)
    	return row[-1]
print(solve_it(m,n))

73.给你一个数 n (1 < n <= 1000000) ,求 n! (n的阶乘)的质因数分解形式. 质因数分解形式为: n=p1m1*p2m2p3^m3…… * 这里 p1 < p2 < p3 < …… 为质数 * 如果 mi = 1, 则 ^ mi 就不需要输出 如:n=6,则输出:6=24*325 n=7,则输出:7=24*3257

def isPrime(value):
	up = int(value ** 0.5) + 1
	for i in range(2, up):
		if i != value and value % i == 0:
			return False
	return True

def Primes(n):
	rsl = []
	for i in range(2, n+1):
		if isPrime(i):
			rsl.append(i)
	return rsl

#n = 6
PrimesList =  Primes(n)
numList = [0] * len(PrimesList)
for i in range(2, n+1):
	for index in range(len(PrimesList)):
		value = i
		while value % PrimesList[index] == 0:
			numList[index] = numList[index] + 1
			value = value / PrimesList[index]
		if value == 1:
			break
#print PrimesList
#print numList
rsl = str(n) + '='
for i in range(len(PrimesList)):
	if numList[i] > 0:
		rsl += str(PrimesList[i])
		if numList[i] != 1:
			rsl += '^' + str(numList[i])
		rsl += '*'
print (rsl[:-1])

74.求组合数 C ( n , k) 的奇偶性. 给你n和k(1<=n<=10^9,0<=k<=n),若其为奇数,则输出1,否则输出0. 如n=2,k=0,则输出1. 因为C(2,0)=1,为奇数。

res = 0
if k == 0 or n == k:
	res = 1
else:
	nn = 0
	while n:
    	nn += (n // 2)
    	n //= 2

	nk = 0
	while k:
    	nk += (k // 2)
    	k //= 2

	if nn > nk:
    	res = 0
	else:
    	res = 1
print(res)


持续更新
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值