师姐内推实习,可惜没有好好准备,半小时都没有完成这道题目,实在有愧.事后诸葛亮,现记录一下题目和求解思路,由于没有case,所以不知对错,欢迎指正.
题目大约如下:所有的同学都站在坐标系上的整数点,由原点看每个点,有的点被视线挡住了,求(长度为N时)原点能看到多少点,如下图所示:比如N = 1时 输出3; N=2时 输出5; N=3时 输出9; N = 4时,输出13?我应该没有算错吧.
看到这道题,我首先想到的就是递归,f(2) = f(1)+ g(2)... f(n) = f(n-1) + g(n), g(n)是关于最外围能看到点的函数.
所有问题在于求g(n)这个函数.最外围能看到几个点呢?首先最外围总共有2*n + 1个点(笔试写成2*n -1了,没注意0也是点), 减去看不到的点就是能看到的点,看不到的点的数应该是N的约数, 那么问题变成求N的约数个数了了. 笔试时想到这个,可惜函数出错了,case还是没过.此时g(n) = 2*n + 1 - ( 2 * N(约数个数) -1)
下面记录一下python(研究生期间一直都是用的python,原谅我python是我最熟的,后面有机会会更新一下c++的代码)的算法,由于没有case给我验证,我也不知道有没有出错的地方,所以解题思路和代码仅供参考,欢迎指正.
"""
Created on Sun Mar 25 15:15:50 2018
@author: hjxu
"""
import numpy as np
def countDivisors(num): #计算有多少个约数,这应该是计算约数时间复杂度最低的吧
cnt = 0
sqrt = int(num ** 0.5)
for x in range(1, sqrt + 1):
if num % x == 0:
cnt += 1
return cnt * 2 - (sqrt ** 2 == num)
def count_num(n):
if n == 1:
return 3
else:
result = np.zeros((n + 1))# 建立一个n+1的数组,用来存放数字
result[1] = 3 # 从1开始,便于理解
for i in range (2,n+1): #循环递归
result[i] = result[i-1] + 2 * i + 1 - ( 2 * countDivisors(i ) -1)
return int(result[n])
n = input('')
if (isinstance(n,int) and n > 0):
print count_num(n)
else:
print 'error! place enter Integer greater than 0'