1. 程式人生 > >第6題——最大的奇約數

第6題——最大的奇約數

http spa next 總結 tin 一半 愛好者 system imp

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

運行超時的代碼:
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
            int N=sc.nextInt();
            int sum=0;
            int i=1;
            while(i<=N){//奇數的最大約數就是本身,直接求和
sum+=i; i=i+2; } int j=2; while(j<=N){//2 6 10 14的最大約數是其一半 sum=sum+j/2; j=j+4; } int k=4; while(k<=N){//其它的數 sum+=evenDivisor(k); k
=k+4; } System.out.println(sum); } sc.close(); } //偶數求最大約數的方法*********超時:算法復雜度過大 private static int evenDivisor(int even){ ArrayList<Integer> arr=new ArrayList<Integer>(); for(int i=1;i<=even;i++){ if(even%i==0){ arr.add(i); } } int res=1; for(int i=0;i<arr.size();i++){ if(arr.get(i)%2==1){ res=arr.get(i); } } return res; } }

還是運行超時的:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
            int N=sc.nextInt();
            int sum=0;
            for(int i=1;i<=N;i++){
                sum+=maxOdd(i);
            }
            System.out.println(sum);
        }
        sc.close();
    }
    //偶數求最大約數的方法
    private static int maxOdd(int m){
        if(m%2==0){
            m=m/2;
            return maxOdd(m);
        }else{
            return m;
        }
    }
}

所以,不能直接求最大約數,必須找到求和的規律

參考代碼:https://www.nowcoder.com/test/question/done?tid=9685251&qid=46577#summary

import java.util.Scanner;

public class Main{
     
    public static void main(String[] args) {
        Scanner s=new Scanner(System.in);
        long num=s.nextInt();
        long sum=0;
        for(long i=num;i>0;i=i/2){
            long temp=(i+1)/2;
            sum+=temp*temp;
        }
        System.out.println(sum);
    }
}
總體思路: 因為奇數的最大奇數約數就是自己啊,對於偶數我們只能一直除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 五個偶數,這是我們再加1 3 5 依次類推 細節問題: 當n為偶數,就有n/2個奇數,根據等差數列求和公式 即((首項+末項)*項數)/2,我們知道n/2個奇數和為((1+n-1)*n/2)/2, 即為(n/2) * (n/2),此時n為偶數,因此 (n/2) * (n/2) = ((n+1)/2) * ((n+1)/2) 當n為奇數,有(n+1)/2個奇數,此時奇數和為((n+1)/2) * ((n+1)/2) 因此兩種情況可以用一個等式來總結

第6題——最大的奇約數