2
3
4
10
100
输出样例
1 1
1 1
2 1
2 2
4 6
每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。
⭐ 合数是可以分解成两个小的质数相乘,所以 所有因子都取 质数,符合尽可能小的题意
⭐ 多重组合排列
import java.util.Scanner;
public class Main
{
static int N = 2000010;
static int[] p = new int[N];// 存质数
static int[] minp = new int[N];// 存 i 对应的最小质因子
static boolean[] st = new boolean[N];
static int cnt;
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
getPrimes(N - 1);
int[] fact = new int[3000];// 记录 x 的所有质因子
int[] sum = new int[N];// 记录某个质因子的次幂(个数)
while (sc.hasNext())
{
int x = sc.nextInt();
int k = 0;// 记录 factor 因子 的个数(去重)
int total = 0;// 总因子个数(可重复)
while (x > 1)
{
int p = minp[x];// 找出 x 的最小质因子
fact[k] = p;
sum[k] = 0;
while (x % p == 0)// 分解质因子
{
x /= p;
sum[k]++;
total++;
}
k++;
}
// 多重排列组合问题
long res = 1;
// n! (n 是总因子数)
for (int i = 1; i <= total; i++)
res *= i;
// n! / a! / b!/ …… (a,b,……是每个因子的个数 (次幂) )
for (int i = 0; i < k; i++)
{
for (int j = 1; j <= sum[i]; j++)
res /= j;
}
System.out.println(total + " " + res);
}
}
private static void getPrimes(int n)
{
for (int i = 2; i <= n; i++)
{
if (!st[i])
{
p[cnt++] = i;
minp[i] = i; // 质数的最小质因子就是它本身
}
// 筛素数(此方法保证了合数一定会被它的最小质因子筛掉)
for (int j = 0; p[j] <= n / i; j++)
{
int t = p[j] * i;
st[t] = true;
minp[t] = p[j];
if (i % p[j] == 0)
break;
}
}
}
}