Leetcode第234周赛 好因子的最大数目

题目描述

Leetcode 第234周赛的T4

5716. 好因子的最大数目(hard) 👈

解题思路

这题难就难在题目的理解上,比如我,开始就压根没看明白(蒟蒻哭泣...

我们来看一下这道题到底想让我们干啥

题目翻译

给你一个正整数 primeFactors 。你需要构造一个正整数 n ,它满足以下条件:

n 质因数(质因数需要考虑重复的情况)的数目 不超过 primeFactors 个。
n 好因子的数目最大化。如果 n 的一个因子可以被 n 的每一个质因数整除,我们称这个因子是 好因子 。比方说,如果 n = 12 ,那么它的质因数为 [2,2,3] ,那么 6 和 12 是好因子,但 3 和 4 不是。
请你返回 n 的好因子的数目。由于答案可能会很大,请返回答案对 10^9 + 7 取余 的结果。

请注意,一个质数的定义是大于 1 ,且不能被分解为两个小于该数的自然数相乘。一个数 n 的质因子是将 n 分解为若干个质因子,且它们的乘积为 n 。

它的意思,其实就是:

  • 有n个质数,分别为:a1, a2, a3, …… an(这里的n只是方便表示,与n质因数的n无关)

  • 每个质数对应一个次幂,分别为:b1, b2, b3, …… bn

因此有:

  • b1 + b2 + …… + bn = primeFactors

  • a1^b1 * a2^b2 * …… * an^bn = 我们构造的n质因数

举个例子

怎么理解这个好因子个数呢,比如我们看看例子1:

输入:primeFactors = 5
输出:6
解释:200 是一个可行的 n 。
它有 5 个质因子:[2,2,2,5,5] ,且有 6 个好因子:[10,20,40,50,100,200] 。
不存在别的 n 有至多 5 个质因子,且同时有更多的好因子。

200包括的质因数有 3 个 2, 2 个 5(primeFactors 为5),那么好因子个数就相当于:

在 3个2 里取出3种情况:【1个2, 2个2, 3个2】

在 2个5 里取出2种情况:【1个5,2个5】

好因子个数为 3 * 2 = 6

[2,5] = 10
[2,2,5] = 20
[2,2,2,5] = 40
[2,5,5] = 50
[2,2,5,5] = 100
[2,2,2,5,5] = 200

思路整理

盘点一下思路

已知:

  • b1 + b2 + …… + bn = primeFactors
  • a1^b1 * a2^b2 * …… * an^bn = 我们构造的n质因数

而我们要求的好因子个数其实就是

  • b1 * b2 * …… * bn 的最大值

也就是说,其实跟我们构不构造那个n质因数没什么关系的!

由于可分配的幂次和是固定的,所以我们为了让幂次的总乘积最高,我们应该用尽可能小的质数做an底数,比如:2,3

我们接着来看个例子:

比如我们输入primeFactors = 6,我们很多种分配方式:

primeFactors 对3取模为0】

  • 1 + 1 + 1 + 1 + 1 + 1 = 6 --> 1 * 1 * 1 * 1 * 1 * 1 = 1(有1就不考虑了,浪费!)

  • 1 + 2 + 3 = 6 --> 1 * 2 * 3 = 6(有1就不考虑了,浪费!)

  • 2 + 2 + 2 = 6 --> 2 * 2 * 2 = 8

  • 2 + 4 =8 --> 2 * 4 = 8

  • 3 + 3 = 6 --> 3 * 3 = 9

发现了吗,3最香,所以,我们应该尽可能的用3来做底数,思路是不是有了?

不信?那我们就拿例子的5来说:

primeFactors 对3取模为2】

  • 2 + 2 + 1 = 5 --> 2 * 2 = 4(同4+1
  • 2 + 3 = 5 --> 2 * 3 = 6
  • 5 = 5 --> 5

总之,优先用3,其次用2

我们可以拿3来作为分界线,对primeFactors 取3模,剩下的用2

但是,我们让primeFactors = 4,情况似乎有变:

primeFactors 对3取模为1】

  • 1 + 3 = 4 --> 1 * 3 = 3
  • 2 + 2 = 4 --> 2 * 2 = 4

为什么这样又不行了,不是优先取3吗?那是因为把4对3取模为1,而1这个东西是浪费的!!!对乘积大小没有贡献!!!所以,我们取次之的2。

通过上面三个例子,我们做个总结:(记primeFactors 为n)

  • n对3取模为0:ans = pow(3,n/3)
  • n对3取模为1:ans = pow(3,n/3 - 1) * 2 * 2
  • n对3取模为2:ans = pow(3,n/3) * 2

坑点

细心的你或许发现了

  • 坑点一:由于答案可能会很大,所以我们要将所有的计算结果对 10^9 + 7 取余(中间结果要加long long)
  • 坑点二:当n=1时,是取模为1的情况,但是它取次幂时候,会变成负次幂,需要我们特殊讨论
  • 坑点三:涉及到大数的次幂计算,所以我们要用快速幂

coding

class Solution {
public:
    // 取模(1e9相当于1*10^9,aeb相当于a*10^b)
    int MOD = 1e9 + 7;
    // 快速幂
    int POW(int a, int b) {
        int res = 1;
        while(b>0) {
            if(b & 1) {
                res = ((long long)res * a) % MOD;
            }
            a = ((long long)a * a) % MOD;
            b = b >> 1;
        }
        return res;
    }
    int maxNiceDivisors(int n) {
        if(n % 3 == 0) {
            return POW(3,n/3);
        }
        else if(n % 3 == 1){
            if(n==1) return 1;
            return ((long long)POW(3,n/3-1) << 2) % MOD;
        }
        else if(n % 3 == 2){
            return ((long long)POW(3,n/3) << 1) % MOD;
        }
        return -1;
    }
};

类似题目

都是换汤不换药的!

感谢

本篇博客参考了这篇题解,以及这个视频

非常感谢大佬们的贡献!!!

最后,希望本文可以帮助到你!😄

posted @ 2021-03-28 18:19  王帅真  阅读(83)  评论(1编辑  收藏  举报