1. 程式人生 > >[程式設計題] 最大的奇約數

[程式設計題] 最大的奇約數

小易是一個數論愛好者,並且對於一個數的奇數約數十分感興趣。一天小易遇到這樣一個問題: 定義函式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