n = a * b * c 题解 by Aze

1.题意

输入一个整型数据 n,拆分成三个因子相乘的形式 a * b * c,且 1 <= a <= b <= c <n,在所有符合要求的 abc 中输出 c-a 最小 且 a 最小的结果

2.分析(copy李哥的思路)

想要求得abc,很容易想到通过三个for循环 a b c 依次从 2 枚举 到 n

可是这样必定超时,所以我们需要缩小枚举范围,优化算法

假设 n = 12

先确定 a 的值

因为 1 <= a <= b <= c <n,而 n = a * b *c

所以 abc 取值最小的是 a * a * a

for (int i = 2; i * i * i <= n; i++)
// 为什么i初始化为2:因为 abc 取值大于1
// i * i * i <= n怎么理解:
//  当 <n 时说明 三个数全取 a 的话 a*a*a 不够n,后面 b 或 c 要大于 a 
//  若使用 i < n 来做,有很多数是没必要用的,比如 11 10 9 8 7等等,会极大的增加时间复杂度
//  数小看不太出来,如果是100000这么大的呢,效果显而易见

当然得保证 i 是n的因子

if (n % i == 0)
// 如 12 % 2 == 0,12除以2没有余数说明2是12的因子

结合一下,我们就能枚举出所有 a 的取值

for(int i = 2; i * i * i <= n; i++)
{
	if(n % i == 0)
	{
	}
}

同样,对于 b,我们既然已经算出 a 的值,那就可以在 n 中除去 a,以便更容易的算出 b

int x = n / a
for (int j = i; j * j <= x; j++)

b 枚举出来之后,还需要一个循环来枚举c吗?很显然,没必要

x / j == c
// 12  = a *  b * c 去掉 a = 2 后 x = 6,即 x = b * c,除去 b 便是 c 的值

结合一下,再加上对 b 是否因子的判断

for(int j = i; j * j <= x; j++)
{
	if( x % j == 0)
}
// 需要加对c是否为因子的判断吗? (x / j) % (x / j) ==0 ? 很显然没必要

至此,我们已经能枚举出所有结果

for(int i = 2; i * i * i <= n; i++)
{
	if(n % i == 0)
	{
        for(int j = i; j * j <= x; j++)
        {
            if( x % j == 0)
            {
                a = i;
                b = j;
                c = x / j;
            }
        }
	}
}

接下来筛选出符合要求的结果并输出

c - a == x / j - i
// 需要保证 其为最小的一个
int temp = 100000; // 声明一个非常大的变量,确保第一次比较能成功
if(x / j - 1 < temp) // 如果当前的结果中 c - a 小于之前结果中的 c - a,则将当前结果置为最终结果 
{
    temp = x / j - i;
    a = i;
    b = j;
    c = x / j;
}
// 至于 a 最小,因为我们是从 a 开始从小到大枚举,所以当满足 c - a 最小时,a 肯定小

现在将其重新组合进去,加上输出判定

for(int i = 2; i * i * i <= n; i++)
{
    int a,b,c,temp = 100000;
	if(n % i == 0)
	{
        for(int j = i; j * j <= x; j++)
        {
            if( x % j == 0 && x / j - i < temp)
            {
                temp = x / j - i;
                a = i;
                b = j;
                c = x / j;
            }
        }
	}
}
if(temp == 100000) printf("No solution\n");// 如果temp没变说明一个结果都没有
else printf("%lld=%d*%d*%d",n,a,b,c);

至此,问题解决!补充一些细节:

#include <cstdio> // 等价于 stdio.h
typedef long long LL; // 等价于 #define LL long long 
const int MAX = 100020; // 等价于 #define MAX 100020
int main()
{
	LL n;
	int count;
	scanf("%d", &count);
	while (count--)
	{
		scanf("%lld", &n);
		int a, b, c, temp = MAX;
		for (int i = 2; i * i * i <= n; i++)
		{
			if (n % i == 0)
			{
				int x = n / i;
				for (int j = i; j * j <= x; j++)
				{
					if (x % j == 0 && x / j - i < temp)
					{
						temp = x / j - i;
						a = i;
						b = j;
						c = x / j;
					}
				}
			}
		}
		if (temp == MAX)
		{
			printf("No solution\n");
			continue;
		}
		else
		{
			printf("%lld=%d*%d*%d", n, a, b, c);
		}
	}
}

讲完!