• 【第30天】给定一个整数 n ,求它的因数之和


    本文已收录于专栏
    🌸《Java入门一百例》🌸

    序、专栏前言

       本专栏开启,目的在于帮助大家更好的掌握学习Java,特别是一些Java学习者难以在网上找到系统地算法学习资料帮助自身入门算法,同时对于专栏内的内容有任何疑问都可在文章末尾添加我的微信给你进行一对一的讲解。
       但最最主要的还是需要独立思考,对于本专栏的所有内容,能够进行完全掌握,自己完完全全将代码写过一遍,对于算法入门肯定是没有问题的。
       算法的学习肯定不能缺少总结,这里我推荐大家可以到高校算法社区将学过的知识进行打卡,以此来进行巩固以及复习。
      学好算法的唯一途径那一定是题海战略,大量练习的堆积才能练就一身本领。专栏的任何题目我将会从【题目描述】【解题思路】【模板代码】【代码解析】等四板块进行讲解。

    一、【例题1】

    1、题目描述

      给定一个整数 n ( 1 ≤ n ≤ 1 e 9 ) n(1\leq n\leq1e9) n(1n1e9),求它的约数之和,答案对 1 e 9 + 7 1e9+7 1e9+7取模

    2、解题思路

    ( 1 ) (1) (1)可以根据求因数个数的代码来求,有 O ( n ) O(n) O(n) O ( n ) O(\sqrt n) O(n )复杂的做法。
    ( 2 ) (2) (2)也可以约数之和定理求解,重点讲解该定理

    3、模板代码

    1)朴素O(n)做法

    import java.util.*;
    
    public class Main {
    	static int mod=1000000007;
        public static void main(String[] args){
            Scanner sc=new Scanner(System.in);
            int n=sc.nextInt();
            long ans=0;
            for (int i = 1; i <=n; i++) {
                if (n%i==0) ans=(ans+i)%mod;
            }
            System.out.println(ans);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2)优化根号n做法

    import java.util.*;
    
    public class test {
    	static int mod=1000000007;
        public static void main(String[] args){
            Scanner sc=new Scanner(System.in);
            int n=sc.nextInt();
            long ans=0;
            for (int i = 1; i <=n/i; i++) {
                if (n%i==0){
                    if (i!=n/i){
                        ans=(ans+i)%mod;
                        ans=(ans+n/i)%mod;
                    }else{
                        ans=(ans+i)%mod;
                    }
                }
            }
            System.out.println(ans);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3)约数之和定理

    import java.util.*;
    
    public class test {
        static int mod=1000000007;
        public static void main(String[] args){
            Scanner sc=new Scanner(System.in);
            int n=sc.nextInt();
            long sum=1;
            for (int i = 2; i <=n/i; i++) {
                if (n%i==0){
                    int c=0;
                    while (n%i==0){
                        c++;
                        n/=i;
                    }
                    long t=1;
                    while (c-->0) t=(t*i+1)%mod;
                    sum=(sum*t)%mod;
                }
            }
            if (n>1) sum=(sum*(n+1)%mod);
            System.out.println(sum);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4、代码解析

    • ( 1 ) (1) (1)前面讲过,对于一个正整数 n n n,由算式基本定理可得:
      n = ∏ i = 1 k p i i = p 1 a 1 × p 2 a 2 × p 3 a 3 . . . . . . p k a k ( p 1 , p 2 . . . . p k 均 为 质 数 ) n=\prod_{i=1}^{k} p_i^{^i}=p_1^{a^1}\times p_2^{a^2}\times p_3^{a^3}......p_k^{a^k}(p_1,p_2....p_k均为质数) n=i=1kpii=p1a1×p2a2×p3a3......pkak(p1,p2....pk)
      那么记 n n n的约束之和为 f ( n ) f(n) f(n),则有:
      f ( n ) = ( p 1 0 + p 1 1 + . . . + p 1 a 1 ) ∗ ( p 2 0 + p 2 1 + . . . + p 2 a 2 ) ∗ . . . ( p k 0 + p k 1 + . . . + p k a k ) f(n)=(p_1^0+p_1^1+...+p_1^{a_1})*(p_2^0+p_2^1+...+p_2^{a_2})*...(p_k^0+p_k^1+...+p_k^{a_k}) f(n)=(p10+p11+...+p1a1)(p20+p21+...+p2a2)...(pk0+pk1+...+pkak)
    • ( 2 ) (2) (2)证明:
      首先计算 p 1 a 1 p_1^{a_1} p1a1的约数之和,可知为 ( p 1 0 + p 1 1 + . . . + p 1 a 1 ) (p_1^0+p_1^1+...+p_1^{a_1}) (p10+p11+...+p1a1)
      其次再算 p 2 a 2 p_2^{a_2} p2a2的约数之和,可知为 ( p 2 0 + p 2 1 + . . . + p 2 a 2 ) (p_2^0+p_2^1+...+p_2^{a_2}) (p20+p21+...+p2a2)

      最后算出 p k a k p_k^{a^k} pkak的约数之和,可知为 ( p k 0 + p k 1 + . . . + p k a k ) (p_k^0+p_k^1+...+p_k^{a_k}) (pk0+pk1+...+pkak)
      根据乘法原理可得, n n n的约数之和 f ( n ) 为 : f(n)为: f(n)
      f ( n ) = ( p 1 0 + p 1 1 + . . . + p 1 a 1 ) ∗ ( p 2 0 + p 2 1 + . . . + p 2 a 2 ) ∗ . . . ( p k 0 + p k 1 + . . . + p k a k ) f(n)=(p_1^0+p_1^1+...+p_1^{a_1})*(p_2^0+p_2^1+...+p_2^{a_2})*...(p_k^0+p_k^1+...+p_k^{a_k}) f(n)=(p10+p11+...+p1a1)(p20+p21+...+p2a2)...(pk0+pk1+...+pkak)
      在这里插入图片描述

    二、【例题2】

    1、题目描述

      给定 n n n 个正整数 a i a_i ai,请你输出这些数的乘积的约数之和,答案对 1 0 9 + 7 10^9+7 109+7 取模。

    2、解题思路

    ( 1 ) (1) (1)在上一题上,由一个数的因数之和拓展为多个数,但本质上乘积的最后仍然为一个数。
    ( 2 ) (2) (2)我们可以将这 n n n个数的都进行质因数的分解,统计每个质因数出现的总次数,最后使用约数之和定理即可。

    3、模板代码

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    
    public class Main {
        static final int mod = 1000000007;
        static Map<Integer, Integer> map = new HashMap<>();
        static long ans = 1;
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            while (n-- > 0) {
                int a = sc.nextInt();
                getNums(a);
            }
            for (Integer a : map.keySet()) {
               long sum=1;
               int k=map.get(a);
               while(k-->0) sum=(sum*a+1)%mod;
               ans=(ans*sum)%mod;
            }
            System.out.print(ans);
        }
        //求质因数公式
        static void getNums(int n) {
            for (int i = 2; i <= n / i; i++) {
                while (n % i == 0) {
                    map.put(i, map.getOrDefault(i, 0) + 1);
                    n /= i;
                }
            }
            if (n > 1) map.put(n, map.getOrDefault(n, 0) + 1);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    三、推荐专栏

    🌌《零基础学算法100天》🌌

    四、课后习题

    序号题目链接难度评级
    1 约数求和2
    👇 学习有疑问?👇
  • 相关阅读:
    力扣linkedlist
    高并发使用JVM锁和MySQL锁解决数据不一致问题
    【Docker项目实战】使用Docker部署HFish蜜罐系统
    什么耳机音质最好又不伤耳朵,什么耳机好用耳朵不疼
    在Pytorch中调用RNN模型的小细节
    手机直播提词器哪个软件好?这两款软件值得收藏
    如何高效处理面板数据
    学习笔记——单调队列与单调栈
    Pandas之datetime数据基础详解。
    C#:计算汉明距离算法​(附完整源码)
  • 原文地址:https://blog.csdn.net/m0_57487901/article/details/125612071