题目名称:凑数
题目描述
给定一组n个正整数,要求每次选其中一个数乘以或除以一个素数(称为一次凑数),问至少需要凑数多少次可以把所有的数都凑成相等。
输入描述:
第一行输入n个正整数(0
输出描述:
可以把所有的数都凑成相等需要至少进行的凑数次数t(t>=0)。@
示例
提示
只要把5乘以2,2次以后就可以得到20。
分析
1)想让所有的数组元素计算后相等
首先从题意上提炼核心点是使得数组的所有元素与一定数量的素数相乘后,所有元素的计算结果相等。这很重要,因为这里提炼成算法思维就是求最小公倍数。解题思路如下:
先数组第一个元素和第二个元素求最小公倍数①,结果①和第三个元素求最小公倍数②,结果②和第四个元素求最小公倍数③...以此类推,直到数组遍历完,我们就得到了数组的最小公倍数。
代码示例
#include <stdio.h>
#include <stdlib.h>
// 欧几里得算法求最大公约数
int gcd(int a, int b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
// 根据公式求最小公倍数
int lcm(int a, int b) {
return (a * b) / gcd(a, b);
}
2)在得到数组的最小公倍数后,我们要去求每一个元素乘以几次素数能够=最小公倍数。由于在前面我们已经求得数组的最小公倍数,此时每个元素需要求的值=最小公倍数/当前元素值=素数1*素数2*素数3*...*素数n。因此问题就变成了如下示意
算法逻辑是
对于整数n,其由几个素数计算得来,遍历2到n之间的所有数,一旦遇到能够被n整除(即n%i == 0)此时就计算n/i由几个素数计算而来。
代码示例
#include <stdio.h>
#include <stdlib.h>
int factorize(int num) {
int count = 0;
for(int i = 2; i <= num; i++) {
while(num % i == 0) {
count++;
num /= i;
}
}
return count;
}
遍历2到n之间的所有数时,由于不是素数的元素已经被前面的元素消除掉了,所以不会存在n%i == 0时i不为素数的情况,例如:当n=20时,如下