网易2017年校招笔试题 最大的奇约数
Posted wangxiaobao的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网易2017年校招笔试题 最大的奇约数相关的知识,希望对你有一定的参考价值。
题目:
定义函数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 + 7 = 21.
分析:
奇数的最大约数是自身, 偶数的最大约数是是除去所有偶因子之后的那个奇数。所以直观的思路就是挨个遍历一遍加起来。
代码:
1 #include <iostream> 2 using namespace std; 3 int main() { 4 long long N; 5 cin >> N; 6 long long result = 0; 7 for (long long i = 1; i <= N; ++i) { 8 int temp = i; 9 while (temp % 2 == 0) { 10 temp /= 2; 11 } 12 result += temp; 13 } 14 cout << result << endl; 15 return 0; 16 }
然而, N的取值范围时10^10,所以O(n)的算法是超时的。
考虑优化,设sum(i) = f(1) + f(2) + ... + f(i);
求sum(i)的过程中,所以f(i), i 为奇数可以直接求,就是 i 本身。
问题就是求所有f(i), i为偶数的和。
因为是最大奇约数,所以f(2k) = f(k),所以f(2) + f(4) + ... + f(2k) = f(1) + f(2) + ... + f(k);
所以
sum(i) = sum (i / 2) + 1 + 3 + ... + i - 1 (i 为偶数)
= sum (i - 1) + i (i 为奇数)
时间复杂度O(logn),可以解决。
1 #include<iostream> 2 using namespace std; 3 long long sum(long long n) { 4 if (n == 1) { 5 return 1; 6 } 7 if (n % 2 == 0) { 8 return sum(n / 2) + n * n / 4; 9 } 10 else { 11 return sum(n - 1) + n; 12 } 13 } 14 int main() { 15 int N; 16 cin >> N; 17 cout << sum(N) << endl; 18 }
以上是关于网易2017年校招笔试题 最大的奇约数的主要内容,如果未能解决你的问题,请参考以下文章