zoukankan      html  css  js  c++  java
  • 第6题——最大的奇约数

    小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数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)
    因此两种情况可以用一个等式来总结
  • 相关阅读:
    自定义TabControl
    认识——转化的力量
    提取网页中的javascript脚本和下载链接
    【作业】简单绘图程序
    遥感中几个物理量计算及比较
    [C++学习]C++内存管理
    小技巧
    Threading.Timer学习
    Unsupported Oracle data type 101 encountered
    Vs2008不能调试的问题
  • 原文地址:https://www.cnblogs.com/dengyt/p/7323887.html
Copyright © 2011-2022 走看看