题意
给你一个数字 n <= 1e9
要你找到三个不同的数字 a , b , c 使得a * b* c == n
存在则输出YES 和 a b c
如果不存在,输出NO
思路
首先我们知道这个数字n,我们能够在O( n 1 2 n^\frac{1}{2} n21)的时间复杂度内算出n的所有因子。
因为是三个数字相乘,所以答案中的三个数字,必定不可能有两个数字同时大于 n 1 2 n^\frac{1}{2} n21,否则他们的乘积肯定要超过n了对吧。
所以我们知道,答案的三个数字中,至少有两个是小于
n
1
2
n^\frac{1}{2}
n21的
假设这两个数字是 a b,则 a * b * c == n,其中 a 和 b 是 n 的因子, c 也是 n 的因子。
所以我们在 n 1 2 n^\frac{1}{2} n21内的因子中枚举a和b,然后看 n a ∗ b \frac{n}{a*b} a∗bn是否是 n 的因子即可求解。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector <int> vec;//2到根号n中的因子
set <int> m_fac;//存除了1和本身的因子
int t, n;
int solve()
{
int cnt = vec.size();
for(int i = 0; i < cnt; i++)
{
for(int j = i + 1; j < cnt; j++)
{
int num = vec[i] * vec[j];
int num2 = n / num;
if(n % num == 0 && num2 != vec[i] && num2 != vec[j] && m_fac.find(num2) != m_fac.end())
{
printf("YES\n");
printf("%d %d %d\n", vec[i], vec[j], num2);
return 0;
}
}
}
printf("NO\n");
return 0;
}
int main()
{
scanf("%d", &t);
while(t--)
{
vec.clear();
scanf("%d", &n);
for(int i = 2; i * i <= n; i++)
{
if(n % i == 0)
{
vec.push_back(i);
m_fac.insert(i);
m_fac.insert(n / i);
}
}
solve();
}
return 0;
}