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

个人思路:

给你说,现在就算是手写,笔算,自己下去画,我都不知道怎样翻转,你还让我编程解决。毫无思路。

正确答案(牛客网 id:TinyJian):

本人比较喜欢数学,就从数学的角度来解这道题吧 设 n = A+B 设 位置值序列集合 E = e 1, e 2, e 3,... e n, e i ∈ 0, 1,其中e i表示第i个位置上的值 (1 ≤ i ≤ n) 假设初始时,前面A个位置为0,后面B个位置为1 设 T i 为 第i个位置上翻转的次数 因为一次翻转必翻转K个位置,假设进行了X次翻转(未知数),则有以下等式 ① XK = ∑T i (1 ≤ i ≤ n) 因为同一个位置翻转2次得到是原来的值,所以为了使所有位置均为1, T 必满足以下条件: ② T i = 1 + 2S i (e 初始为0) ③ T i = 2S i(e i 初始为1) 其中S 表示第i个位置进行了 S i次2次翻转 结合①、②、③可得: ④ XK = A + 2 ∑S i (1 ≤ i ≤ n) ⑤  XK - A 必为偶数 我对此的理解为,总的来看:在某些位置上进行了2次翻转,和A个位置的1次翻转,就全部为1了。 对 ∑S i 观察可得: 对于初始为1的位置,2次翻转次数不能超过X/2 对于初始为0的位置,2次翻转次数不能超过(X-1)/2 ,因为最后一次翻转不能属于“2次翻转”中的一次翻转 我们假设所有位置的2次翻转次数都达到最大,则有不等式: ⑥ ( XK - A)/2 = ∑S i (1 ≤ i ≤ n) ≤ A ((X-1)/2) + B(X/2) 满足⑤、⑥条件X即可满足题意 我们可以相信,X不能大于 A的最大值+B的最大值 = 200000 2017年校招全国统一模拟笔试(第四场)编程题集合--Python

2017年校招全国统一模拟笔试(第四场)编程题集合--Python

2017年校招全国统一模拟笔试(第二场)编程题集合--Python

2017年校招全国统一模拟笔试(第三场)编程题集合--Python

2017年校招全国统一模拟笔试(第三场)编程题集合--Python

头条18年校招后端开发工程师编程题解析

(c)2006-2024 SYSTEM All Rights Reserved IT常识