题目
题目描述
输入正整数(X),求(X)的大于(1)的因子组成的满足任意前一项都能整除后一项的严格递增序列的最大长度,以及满足最大长度的序列的个数。
输入格式
输入包含多组数据,每组数据占一行,包含一个正整数表示(X)。
输出格式
对于每组数据,输出序列的最大长度以及满足最大长度的序列的个数。
每个结果占一行。
数据范围
(1 le X le 2^{20})
输入样例:
2
3
4
10
100
输出样例:
1 1
1 1
2 1
2 2
4 6
分析
算数基本定理:任何一个大于(1)的自然数(N),如果(N)不为质数,那么(N)可以唯一分解成有限个质数的乘积(N=P_1^{a_1}P_2^{a_2}P_3^{a_3}......P_n^{a_n}),这里(P1<P2<P3......<Pn)均为质数,其中指数(a_i)是正整数。
后一项能整除前一项,即后一项为前一项乘任意一个质因子(P_i)。最大长度由分解质因数可得,即(maxLength=sumlimits_{n=1}^na_n)。
本题还问到了满足最长序列的个数,即求所有质因子的全排列,但由于其中有重复的元素,所以转换成多冲击组合数问题。(多重集组合数:一共有(k)种物品,每一种有(n_i)个,(1le ile k),总共有(n)个物品,则(n)个物品的全排列为(frac{n!}{n_1!n_2!n_3!...n_k!}))
用到的知识
1.算数基本定理以及质因数分解
2.多重集组合数
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = (1 << 20) + 10;
int x;
int fact[30], sum[30];
LL f(int n)
{
LL res = 1;
for (int i = 1; i <= n; i++)
res *= i;
return res;
}
int main()
{
while (scanf("%d", &x) != EOF)
{
int k = 0;
for (int i = 2; i <= x / i; i++)
{
if (x % i == 0) fact[++k] = i;
while (x % i == 0)
{
sum[k]++;
x /= i;
}
}
if (x != 1) fact[++k] = x, sum[k]++;
int tot = 0;
for (int i = 1; i <= k; i++)
tot += sum[i];
LL res = f(tot);
for (int i = 1; i <= k; i++)
res /= f(sum[i]);
cout << tot << " " << res << endl;
memset(sum, 0, sizeof(sum));
}
return 0;
}