本篇博客会讲解力扣“2427. 公因子的数目”的解题思路,这是题目链接。
本题的思路是:
由于a和b公因子的个数就是a和b的最大公约数的因子的个数,所以我们需要思考以下2个问题:
- 如何求解最大公约数?
- 如何求解正整数的因子个数?
求解最大公约数,效率最高的思路是辗转相除法。若求a和b的最大公约数,需要每次a mod b得到m,若m不是0,则把b赋值给a,m赋值给b,再次求解a mod b,直到m为0时,b就是最大公约数。
求解正整数m的因子个数,可以枚举[1,m]的所有整数,判断是不是m的因子。这个思路可以优化一下,只需要枚举[1,sqrt(m)]的所有整数,其中sqrt是算术平方根的意思。这是因为,因子总是成对出现的,比如10的因子有1、2、5、10,其中1和10,2和5分别是1对,它们的乘积都是10,而每一对的较小值一定不大于sqrt(n)。我们只需要统计[1,sqrt(m))中的数,若是n的因子,则因子的总个数加2。但是需要注意一点,若sqrt(n)是整数,那么sqrt(n)本身也是n的因子,此时虽然是成对出现的,但是个数不是加2,而是加1,这点需要分开讨论。
// 求最大公约数
int gcd(int a, int b)
{
int m = 0;
// 辗转相除,直到余数为0
while (m = a % b)
{
a = b;
b = m;
}
return b;
}
int commonFactors(int a, int b){
// 求最大公约数
int m = gcd(a, b);
int cnt = 0; // 因子个数
int i = 1;
for (; i * i < m; ++i)
{
// 最大公约数的因子也是a和b的因子
if (m % i == 0)
cnt += 2;
}
// 判断sqrt(m)是不是整数
if (i * i == m)
++cnt;
return cnt;
}
总结
- 求解最大公约数可以使用辗转相除法。
- a和b的公因子个数,等价于a和b的最大公约数的因子个数。
- 正整数n的因子总是成对出现的,每一对的较小值不大于sqrt(n)。
感谢大家的阅读!