2017年校招全国统一模拟笔试(第一场)编程题集合--Python
Posted zy_dream
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017年校招全国统一模拟笔试(第一场)编程题集合--Python相关的知识,希望对你有一定的参考价值。
注:试题来源于牛客网
1.
牛牛有一个鱼缸。鱼缸里面已经有n条鱼,每条鱼的大小为fishSize[i] (1 ≤ i ≤ n,均为正整数),牛牛现在想把新捕捉的鱼放入鱼缸。鱼缸内存在着大鱼吃小鱼的定律。经过观察,牛牛发现一条鱼A的大小为另外一条鱼B大小的2倍到10倍(包括2倍大小和10倍大小),鱼A会吃掉鱼B。考虑到这个,牛牛要放入的鱼就需要保证:1、放进去的鱼是安全的,不会被其他鱼吃掉
2、这条鱼放进去也不能吃掉其他鱼
鱼缸里面已经存在的鱼已经相处了很久,不考虑他们互相捕食。现在知道新放入鱼的大小范围[minSize,maxSize](考虑鱼的大小都是整数表示),牛牛想知道有多少种大小的鱼可以放入这个鱼缸。
输入描述:
输入数据包括3行. 第一行为新放入鱼的尺寸范围minSize,maxSize(1 ≤ minSize,maxSize ≤ 1000),以空格分隔。 第二行为鱼缸里面已经有鱼的数量n(1 ≤ n ≤ 50) 第三行为已经有的鱼的大小fishSize[i](1 ≤ fishSize[i] ≤ 1000),以空格分隔。
输出描述:
输出有多少种大小的鱼可以放入这个鱼缸。考虑鱼的大小都是整数表示
输入例子:
1 12 1 1
输出例子:
3
个人思路:
我是从输入的鱼范围大小入手,从最小到最大,以此进行判断。 与鱼缸中鱼的大小做 /,如果能除尽,就是被吃。反之,则可以增加一次大小。 我的测试用例是 30% case 1 36 1 3 答案输出 10 我的是 8 鱼缸中的一条鱼大小是 3,则可放入鱼的大小为 2,3,4,5,7,8,10,11,13,14,16,17,19,20,22,23,25,26,28,29,31.... 我是真没弄明白这题的意思。来看看正确答案吧。 分割线: 在分析了一波正确答案之后,我再看题,我明白了,2倍到10倍是一个什么概念!是区间啊大哥。我理解的是,是一个数的2倍,3倍,或者...10倍中的一个。正确答案(牛客网 id:cheeeenkun):
minSize, maxSize = map(int,raw_input().split())
n = map(int,raw_input())
fishSize = map(int,raw_input().split())
put_in = range(minSize,maxSize+1)
cannot_input = 0
for x in put_in:
flag = 0
for i in fishSize:
if 2*x <= i <=x*10 or i*2 <= x <=i*10:
flag = 1
if flag == 1:
cannot_input += 1
print maxSize+1-minSize-cannot_input
2.
如果一个单词通过循环右移获得的单词,我们称这些单词都为一种循环单词。 例如:picture 和 turepic 就是属于同一种循环单词。 现在给出n个单词,需要统计这个n个单词中有多少种循环单词。输入描述:
输入包括n+1行: 第一行为单词个数n(1 ≤ n ≤ 50) 接下来的n行,每行一个单词word[i],长度length(1 ≤ length ≤ 50)。由小写字母构成
输出描述:
输出循环单词的种数
输入例子:
5 picture turepic icturep word ordw
输出例子:
2
个人思路:
必须是右移 不,这个是相对的 例子中,ture是右移的,但是pic就是相对左移 那简单了,先对每一个单词排序,然后set,最后len(set)当时我是这样思考的,但测试用例 70% case,错误例子:
测试用例:
7
ast
ats
tas
tsa
sat
sta
ttt
对应输出应该为:
3
你的输出为:
2
果然我考虑的循环移动是有问题的,没有彻底思考究竟是什么循环右移。看到一个思路方法: 把要测试的单词后再重复下这个单词,如:picture ,变成 picturepicture
然后判断其他要测试的单词是不是这个串的子串(长度要先相等)
正确方法(牛客网 id:周昆):
def judge(word1, word2):
if len(word1) != len(word2):
return False
for i in range(len(word1)):
if word1[i:] + word1[:i] == word2:
return True
else:
return False
n = int(raw_input())
rec = list()
for i in range(n):
flag = True
word1 = raw_input()
for word2 in rec:
if judge(word1, word2):
flag = False
break
if flag:
rec.append(word1)
print len(rec)
这个貌似就是用了上面思路,通过 python 数组的分割 [3:] [:3] 来进行判断。就是以此把前面1,2..位的字符放到末尾去
so,循环右移就是把左边的连续字符移到右边去即可。
3.
DNA分子是以4种脱氧核苷酸为单位连接而成的长链,这4种脱氧核苷酸分别含有A,T,C,G四种碱基。碱基互补配对原则:A和T是配对的,C和G是配对的。如果两条碱基链长度是相同的并且每个位置的碱基是配对的,那么他们就可以配对合成为DNA的双螺旋结构。现在给出两条碱基链,允许在其中一条上做替换操作:把序列上的某个位置的碱基更换为另外一种碱基。问最少需要多少次让两条碱基链配对成功输入描述:
输入包括一行: 包括两个字符串,分别表示两条链,两个字符串长度相同且长度均小于等于50。
输出描述:
输出一个整数,即最少需要多少次让两条碱基链配对成功
输入例子:
ACGT TGCA
输出例子:
0
个人思路:
这题是属简单题,我这里用了先得出一条链的配对链,然后去计算另外一条链需要变化多少次正确答案(本人&&牛客网 id:Panzerfaust):
def combine(arr):
wife = []
for a in arr:
if a == 'A':
wife.append('T')
elif a == 'T':
wife.append('A')
elif a == 'C':
wife.append('G')
elif a == 'G':
wife.append('C')
return wife
arr = [s for s in raw_input().strip().split()]
a = list(arr[0])
b = list(arr[1])
c = combine(a)
i = 0
count = 0
while i < len(a):
if c[i] != b[i]:
count += 1
i += 1
print count
精简的代码;
try:
while 1:
line = raw_input().split()
count =0
tmp = ["AT","TA","GC","CG"]
for i in range(len(line[0])):
if line[0][i]+line[1][i] not in tmp:
count+=1
print(count)
except:
pass
这个妙啊,妙啊,妙啊!!!
4.
牛牛的好朋友羊羊在纸上写了n+1个整数,羊羊接着抹除掉了一个整数,给牛牛猜他抹除掉的数字是什么。牛牛知道羊羊写的整数神排序之后是一串连续的正整数,牛牛现在要猜出所有可能是抹除掉的整数。例如:10 7 12 8 11 那么抹除掉的整数只可能是9
5 6 7 8 那么抹除掉的整数可能是4也可能是9
输入描述:
输入包括2行: 第一行为整数n(1 <= n <= 50),即抹除一个数之后剩下的数字个数 第二行为n个整数num[i] (1 <= num[i] <= 1000000000)
输出描述:
在一行中输出所有可能是抹除掉的数,从小到大输出,用空格分割,行末无空格。如果没有可能的数,则输出mistake
输入例子:
2 3 6
输出例子:
mistake
个人思路:
我的整体思路就是,先对 n+1 数进行排序,然后从首尾数字入手进行一系列操作即可咯。 哇,就在刚才,我最终还是修改成功了呢。 之前重复的数字,加了一个判断 另外一个小问题就是必须是正整数 可以的,果然写博客不错哟正确答案(本人&&牛客网 id:Cheeeenkun):
n = int(raw_input())
arr = [int(i) for i in raw_input().strip().split()]
ar = sorted(arr)
first = ar[0]
end = ar[n-1]
middle = n - 2
init = []
result = []
for i in range(first, end+1, 1):
init.append(i)
init_middle = len(init) - 2
if init_middle - middle > 1:
print 'mistake'
elif len(ar) != len(list(set(arr))):
print 'mistake'
else:
if ar == init:
a = ar[0] - 1
if a > 0:
result.append(str(a))
b = ar[n-1] + 1
if b > 0:
result.append(str(b))
else:
i = 0
j = 0
temp = sorted(ar[:])
while i < n and j < len(init):
if temp[i] != init[j]:
if init[j] > 0:
result.append(str(init[j]))
j += 1
else:
i += 1
j += 1
print ' '.join(result)
重复数字那里使用 list 和 set,自从会用了这两个好多问题解决起来很方便。
n = int(raw_input())
numbers_ = map(int,raw_input().split())
max_number = max(numbers_)
min_number = min(numbers_)
result = set(range(min_number,max_number+1))-set(numbers_)
if len(result) == 1:
print list(result)[0]
elif len(result) == 0:
if min_number-1 > 0:
print min_number-1,max_number+1
else:
print max_number+1
elif len(result) > 1:
print 'mistake'
这个 ce 大佬前面那题代码就很妙,哇!还是一个字,太妙了!
亮点在 result = set... 这一句,用 set 集合的关系!哇哇哇!膜拜吧
5.
如果一个数字能表示为p^q(^表示幂运算)且p为一个素数,q为大于1的正整数就称这个数叫做超级素数幂。现在给出一个正整数n,如果n是一个超级素数幂需要找出对应的p,q。输入描述:
输入一个正整数n(2 ≤ n ≤ 10^18)
输出描述:
如果n是一个超级素数幂则输出p,q,以空格分隔,行末无空格。 如果n不是超级素数幂,则输出No
输入例子:
27
输出例子:
3 3
个人思路:
这题我算是误打误撞,但还是 40 % case,因为数据太大,时间就超了,而且我只是一个求因子的过程,并没有判断素数def yinshi(n):
y = []
i = 2
while i <= n :
if n % i == 0:
n = n / i
y.append(i)
else:
i += 1
return y
n = int(raw_input())
if len(list(set(yinshi(n)))) != 1:
print 'No'
else:
print list(set(yinshi(n)))[0], len(yinshi(n))
貌似是不是判断了素数,我时间也还是超时了。
分割线: 果然加了素数判断还是时间问题。
正确答案(牛客网 id:che.jianglin):
import math
n = int(raw_input())
l = int(math.log(n,2))
def isPrime(x):
if x<=1:
return False
for i in xrange(2,int(math.sqrt(x))+1):
if x%i==0:
return False
return True
# print(isPrime(3))
flag = True
for i in xrange(2,l+1):
p = math.pow(n,1.0/i)
if(p-int(p)==0 and isPrime(p)):
flag = False
print int(p),i
break;
if(flag):
print "No"
果然是数学问题,用了 log 对数函数,然后在用 pow 幂函数。
而我自己问题出在不应该用 while。
6.
给出一个正整数N和长度L,找出一段长度大于等于L的连续非负整数,他们的和恰好为N。答案可能有多个,我我们需要找出长度最小的那个。例如 N = 18 L = 2:
5 + 6 + 7 = 18
3 + 4 + 5 + 6 = 18
都是满足要求的,但是我们输出更短的 5 6 7
输入描述:
输入数据包括一行: 两个正整数N(1 ≤ N ≤ 1000000000),L(2 ≤ L ≤ 100)
输出描述:
从小到大输出这段连续非负整数,以空格分隔,行末无空格。如果没有这样的序列或者找出的序列长度大于100,则输出No
输入例子:
18 2
输出例子:
5 6 7
个人思路:
求 1 - N-1 的连续数列中,和等于 N 的长度最小数列 先从 L + 1 个长度计算,如果数列中有符合条件的值,则直接输出这个序列 否则的话, L ++ 继续求 那么,又是时间的问题小的数字都可以完成要求,输入的数字如果太大,那么就不行。
arr = [int(i) for i in raw_input().strip().split()]
N = arr[0]
L = arr[1]
num = list(xrange(1, N+1))
j = 0
z = 1
k = L + z
add = sum(num[j:k])
while k < len(num):
if add == N:
break
else:
j += 1
k += 1
add = sum(num[j:k])
if k == len(num)-1:
z += 1
k = L + z
j = 0
add = sum(num[j:k])
if add != N or k-j > 100:
print 'No'
else:
m = map(str, num[j:k])
print ' '.join(m)
例如:
100 4
18 19 20 21 22 这都是可以完成的。 看到的另外一个思路: 等差数列求和: S = (2*a1+n-1) / 2 a1 = 2 * S + n - n^2 / 2 *n n 从 L 到 100 找出满足的 a1,输出 嗯,总的来说,就是根据公式来求 a1,然后输出 a1 之后的 i 即 L 位 哇,我记得当时貌似是有想到等差数列,结果没太深入想。
正确答案(牛客网 id:Panzerfaust):
import math
import sys
def judge(m,n):
for i in range(n,101):
start = int((2*m/i-i+1)/2)
if int((start+start+i-1)*i/2) == m:
return ' '.join([str(var) for var in range(start,start+i)])
return "No"
for line in sys.stdin:
a = [int(var) for var in line.split()]
print(judge(a[0],a[1]))
start = a1
7.
牛牛新买了一本算法书,算法书一共有n页,页码从1到n。牛牛于是想了一个算法题目:在这本算法书页码中0~9每个数字分别出现了多少次?输入描述:
输入包括一个整数n(1 ≤ n ≤ 1,000,000,000)
输出描述:
输出包括一行10个整数,即0~9这些数字在页码中出现的次数,以空格分隔。行末无空格。
输入例子:
999
输出例子:
189 300 300 300 300 300 300 300 300 300
个人思路:
不得不说,这一题我又是被大整数搞蹦了。而我完全没想到这样的算法来解决此题, 我只用了偷鸡的方法。dic = '1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0, '9': 0, '0': 0
page = int(raw_input())
arr = list(xrange(1, page+1))
for a in arr:
num = list(str(a))
for n in num:
dic[n] += 1
print dic['0'], dic['1'], dic['2'], dic['3'], dic['4'], dic['5'], dic['6'], dic['7'], dic['8'], dic['9']
和算法相比,我真特么会选方法。
会个P啊会。
正确答案(牛客网 id:zero_python):
num = int(raw_input())
def find(num):
# 计算每个数字, 在每一位上出现的次数.
res = [0] * 10
digit = 1 # 个位
while True:
low = num % digit
cur = (num % (10 * digit)) / digit
high = num / (10 * digit)
if cur == 0 and high == 0:
break
# 各个数字在digit位上出现了几次?
for i in range(10):
if i < cur:
if i == 0:
res[i] += high * digit
else:
res[i] += (high+1) * digit
elif i == cur:
if i==0:
res[i] += (high-1) * digit + low + 1
else:
res[i] += high * digit + low + 1
else:
if i == 0:
res[i] += (high-1) * digit
else:
res[i] += high * digit
digit *= 10 # 下一位
return res
res = find(num)
print ' '.join(map(str, res))
给大家提供一种思路(牛客网 Id: 天祺):
2位数的情况: N=13,个位数出现的1的次数为2,分别为1和11,十位数出现1的次数为4,分别为10,11,12,13,所以f(N) = 2+4。 N=23,个位数出现的1的次数为3,分别为1,11,21,十位数出现1的次数为10,分别为10~19,f(N)=3+10。 由此我们发现,个位数出现1的次数不仅和个位数有关,和十位数也有关,如果个位数大于等于1,则个位数出现1的次数为十位数的数字加1;如果个位数为0,个位数出现1的次数等于十位数数字。而十位数上出现1的次数也不仅和十位数相关,也和个位数相关:如果十位数字等于1,则十位数上出现1的次数为个位数的数字加1,假如十位数大于1,则十位数上出现1的次数为10。 3位数的情况: N=123 个位出现1的个数为13:1,11,21,…,91,101,111,121 十位出现1的个数为20:10~19,110~119 百位出现1的个数为24:100~123 我们可以继续分析4位数,5位数,推导出下面一般情况: 假设N,我们要计算百位上出现1的次数,将由三部分决定:百位上的数字,百位以上的数字,百位一下的数字。 如果百位上的数字为0,则百位上出现1的次数仅由更高位决定,比如12013,百位出现1的情况为100~199,1100~1199,2100~2199,…,11100~11199,共1200个。等于更高位数字乘以当前位数,即12 * 100。 如果百位上的数字大于1,则百位上出现1的次数仅由更高位决定,比如12213,百位出现1的情况为100~199,1100~1199,2100~2199,…,11100~11199,12100~12199共1300个。等于更高位数字加1乘以当前位数,即(12 + 1)*100。
如果百位上的数字为1,则百位上出现1的次数不仅受更高位影响,还受低位影响。例如12113,受高位影响出现1的情况:100~199,1100~1199,2100~2199,…,11100~11199,共1200个,但它还受低位影响,出现1的情况是12100~12113,共14个,等于低位数字13+1。
8.
牛牛正在挑战一款名为01翻转的游戏。游戏初始有A个0,B个1,牛牛的目标就是把所有的值都变为1,每次操作牛牛可以任意选择恰好K个数字,并将这K个数字的值进行翻转(0变为1,1变为0)。牛牛如果使用最少的操作次数完成这个游戏就可以获得奖品,牛牛想知道最少的操作次数是多少?例如:A = 4 B = 0 K = 3
0000 -> 1110 -> 1001 -> 0100 -> 1111
需要的最少操作次数为4
输入描述:
输入为一行: 一共三个整数A(0 ≤ A ≤ 100,000),B(0 ≤ B ≤ 100,000),K(1 ≤ K ≤100,000).以空格分隔
输出描述:
输出一个整数,表示最少需要的操作次数。如果不能完成,则输出-1
输入例子:
4 0 3
输出例子:
4