小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数f(x)为x最大的奇数约数,x为正整数。 例如:f(44) = 11.
现在给出一个N,需要求出 f(1) + f(2) + f(3)…….f(N)
例如: N = 7
f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) = 1 + 1 + 3 + 1 + 5 + 3 + 7 = 21
小易计算这个问题遇到了困难,需要你来设计一个算法帮助他。
我的想法是样的,前n个数中,我们可以把任意一个偶数表示成一个奇数和一个偶数的乘积,例如
8=23∗1,10=2∗5,18=2∗9
,等等。 再扩展一步,前n个数中,任意数都可以表示成:
x=2k∗j,k=0,1,2,...,m
这里的x是任意小于等于n的数,j是某一个奇数,那么我们现在看一下m的大小(懒得打公式,也不是很会…):
即m为
[log2n]
[]是向下取整符号
这样我们就可以计算每个k对应有多少个j符合要求的,假设为分别为
k1,k2,...,km
个,再用奇数的前n项和公式,k2i,i=0,1,2,...,m
,求和,累计相加即可。下面给出一些例子: 这里只剩下计算每个
ki
对应的奇数的个数j了。
从上面例子可以看出j的值为
([n/2i]+1∗y)/2
其中[ ]表示向下取整,y=0,当且仅当 [n/2^i]为偶数,y=1当且仅当[n/2^i]为奇数。下面给出python程序
def get_j_sum(n):
import math
def get_k_j_sum(ki):
return ki**2
def get_j_num(k):
if k%2!=0:
return (k+1)/2
else:
return k/2
m = math.floor(math.log(n, 2))
s=0
for i in range(int(m+1)):
k=math.floor(float(n)/(2**i))
ki=get_j_num(k)
s+=get_k_j_sum(ki)
return int(s)
然而,牛客上我的正确率只有60%,不知道哪位大神帮我找出错误呢???这个在计算100000000的时候与标准答案差了150,望大神指点指点