[程式設計題] 最大的奇約數
小易是一個數論愛好者,並且對於一個數的奇數約數十分感興趣。一天小易遇到這樣一個問題: 定義函式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 (1 ≤ N ≤ 1000000000)
輸出描述:
輸出一個整數,即為f(1) + f(2) + f(3)…….f(N)
輸入例子:
7
輸出例子:
21
解題思路:易知當n為偶數,f(n)=f(n/2),n為奇數,f(n)=n。
因為n是10億,O(n)肯定超時,所以需要求遞推公式。
舉例:
Sum(6)=f(1)+f(2)+f(3)+f(4)+f(5)+f(6)
=f(1)+f(1)+f(3)+f(2)+f(5)+f(3)
=f(1)+f(3)+f(5)+f(1)+f(2)+f(3)
=Sum(3)+1+3+5
所以:
sum(n) = sum (n / 2) + 1 + 3 + … + n - 1 (n 為偶數)
= sum (n / 2) + (1 + n - 1)*(n/2) /2
= sum (n / 2) +n*n/4
sum(n) =sum(n-1)+n (n位奇數)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
long long Find(int n){
long long sum=0;
while(n>0){
if(n%2==0){
sum+=n*n/4;
n/=2;
}else{
sum+=n;
n--;
}
}
return sum;
}
int main()
{
int n;
scanf("%d",&n);
printf("%d\n",n);
long long ans=0;
printf("%lld\n",Find(n));
return 0;
}
但是這個程式碼提交是WRONG的。
我想int 的範圍表示10億是夠的,用int表示輸入應該是OK的,
但是沒注意 sum+=n*n/4 這句,n*n就會直接爆掉。
所以需要把int n改為long long n