题目
小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数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
小易计算这个问题遇到了困难,需要你来设计一个算法帮助他。
解答
本来这个题挺简单的,分分钟写出来:
#include<iostream>
using namespace std;
int f(int n){
while(n%2==0)
n = n/2;
return n;
}
int main(){
int N;
cin>>N;
int res = 0;
for(int i=0;i<N;i++){
res = res+f(i);
}
cout<<res;
}
结果时间复杂度有点大。。。没通过。
只能换一种方法,奇数的最大奇因数是其本身,所以奇书直接相加,把N除以2,得到的1-N/2即是原先的每个偶数除以2得到的序列。再用同样的方法进行处理。
比如1 2 3 4 5 6 7 8 9 10
即n=10 ,此时奇数有1 3 5 7 9 我们把这几个奇数相加然后n/2
得到第二轮序列序列 1 2 3 4 5 分别对应上次的2 4 6 8 10 五个偶数。
求和时用等差求和公式,注意n为偶数时,n/2=(n+1)/2
#include<iostream>
using namespace std;
int main(){
long long N;
cin>>N;
long long res = 0;
for(long long i=N;i>0;i=i/2){
res = (((i+1)/2)*((i+1)/2))+res;
}
cout<<res;
}