Leetcode第234周赛 好因子的最大数目
题目描述
Leetcode 第234周赛的T4
解题思路
这题难就难在题目的理解上,比如我,开始就压根没看明白(蒟蒻哭泣...
我们来看一下这道题到底想让我们干啥
题目翻译
给你一个正整数 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;
}
};
类似题目
都是换汤不换药的!
感谢
非常感谢大佬们的贡献!!!
最后,希望本文可以帮助到你!😄