【跟着英雄哥学算法第(12)讲】力扣1390.四因数 [c语言]

261 阅读2分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路

小插曲

          这是初学算法的我  

 

             这是加入万人学习社区的我 

        在此,博主准备分享一个万人学习的社区,这里有许多大佬指引前行,大家互相勉励学习,欢迎大家加入这个社区。博主也是小白,理解大家的困惑,一个人学习太艰难了,不容易走的很远。 

      万人千题社区       https://bbs.csdn.net/forums/hero?category=0


文章目录


四因数

                           力扣 1390.四因数  https://leetcode-cn.com/problems/four-divisors/                              

 


 

一.方法一

       枚举

      我们可以遍历数组 nums 中的每个元素,依次判断这些元素是否恰好有四个因数。对于任一元素 x,我们可以用类似质数判定的方法得到它的因数个数,其本质为:如果整数 x 有因数 y,那么也必有因数 x/y,并且 y 和 x/y 中至少有一个不大于 sqrt(x)。这样我们只需要在 [1, sqrt(x)] 的区间内枚举可能为整数 x 的因数 y,并通过 x/y 得到整数 x 的其它因数。如果x恰有四个因数,将其相加即可。

        代码如下 

int sumFourDivisors(int* nums, int numsSize) {
    int m = 0;                                //题目要求如果数组中不存在满足题意的整数,则返回 0 ,故此定义。
    for (int i = 0; i < numsSize; i++) {      //遍历数组
        int count = 0; int sum = 0;           //注意定义count,sum=0的位置
        for (int j = 1; j <= sqrt(nums[i]); j++) {//j属于此范围[1, sqrt(x)]
            if (nums[i] % j == 0) {               
                count++;
                sum += j;
                if (j * j != nums[i]) {          //当相等时,为停止循环的条件
                    count++; sum += nums[i] / j;
                }
            }
        }if (count == 4) m += sum;              //count==4时 m+=sum
    }return m;

}

二. 方法二

    求一个数n的因子和

           (1)对n进行素数分解后,最小素数的为p素因子p的个数为e,那 

                                                      

(2)当n的因子中p的个数为0,因子之和为s(n')。若n的因子中p的个数为k,因子之和

              

        (3)所有的因子之和为

                                    

      (4)s(n')使用等比数列可化为

 

   <1>分析题目

    根据因子的定义,共分两种情况

(1)两个素数的乘积,即x=pq:

``

(2)某个素数的三次幂,即x=p的三次方:

``

   <2>源码解析


#define maxn 100001   //  数组上限100001
#define ll long long

bool f[maxn];
int primes[maxn];

void ethPrime() {                                  //以下为埃式筛法
    int i;
    ll j;
    f[0] = f[1] = 1;
    primes[0] = 0;                                  
    for (i = 2; i < maxn; ++i) {                   
        if (!f[i]) {
            primes[++primes[0]] = i;
            for (j = (ll)i * i; j < maxn; j += i) {
                f[j] = 1;
            }
        }
    }
}

bool isPrime(int x) {
    return !f[x];
}

int sumFourDivisors(int* nums, int numsSize) {
    int i, j, p, q;
    int ans = 0;
    ethPrime();                                  
    for (i = 0; i < numsSize; ++i) {              
        for (j = 1; j <= primes[0]; ++j) {        
            p = primes[j];                             //(1)和(2)对称解法求素数
            if (nums[i] % p == 0) {                    //素数的判断
                q = nums[i] / p;                       //(2)  
                if (isPrime(q) && p != q) {
                    ans += (p + 1) * (q + 1);         // 因子数的第一种情况
                }
                if (q == (long long)p * p) {
                    ans += p * p * p + p * p + p + 1; // 因子数的第二种情况
                }
                break;
            }
        }
    }
    return ans;
}

补充

  简单补充一下埃式筛法