序列长度:x的所有质因子的个数
序列个数:就是x质因子的全排列数,但是要去掉重复的,(例:如果质因子2的数量为3,那么所有2内部的排列都算是一样的)
这就是多重集组合数:给定n种物品,每个物品对应的有ni个,那么去掉重复的全排列数为:(n1+n2+…nn)!/n1! n2!…nn! (因为每种排列,多算了相同的数内部的全排列)
算法:
1. 要先求每个数的最小质因子 (线性筛素数法)
2. 分解读入的数的质因子,用数组存下来每个质因子的数量。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N = (1 << 20) + 5;
int primes[N], minp[N], cnt = 0;
bool st[N];
void get_primes(int n){
for (int i = 2; i < n; ++i){
if (!st[i]) primes[cnt++] = i, minp[i] = i;
for (int j = 0; primes[j] * i < n; ++j){
int t = primes[j] * i;
st[t] = true;
minp[t] = primes[j];
if (i % primes[j] == 0) break;
}
}
}
int main(void){
get_primes(N);
int x;
while (cin >> x){
int sum[25], k = 0, tot = 0;
while (x > 1){
int p = minp[x]; // 得到当前数的最小质因子p,p肯定也是初始x的质因子之一,并且p是逐渐变大的,因为一开始分离的是最小的,然后分离的是第二小的
sum[k] = 0;
while (x % p == 0){ // 当x仍然是p的倍数时,将质因子p全部分离
x /= p;
sum[k]++; // 每个质因子计数
tot++; // 记总个数
}
k++;
}
LL res = 1;
for (int i = 1; i <= tot; ++i) res *= i;
// cout << res;
for (int i = 0; i < k; ++i){
for (int j = 1; j <= sum[i]; ++j) res /= j;
}
cout << tot << ' ' << res << endl;
}
return 0;
}