X的因子链【多重集的排列数问题】

X的因子链

输入正整数 X,求 X 的大于 1 的因子组成的满足任意前一项都能整除后一项的严格递增序列的最大长度,以及满足最大长度的序列的个数。

输入格式
输入包含多组数据,每组数据占一行,包含一个正整数表示 X。

输出格式
对于每组数据,输出序列的最大长度以及满足最大长度的序列的个数。

每个结果占一行。

数据范围
\(1≤X≤2^{20}\)
输入样例:
2
3
4
10
100
输出样例:
1 1
1 1
2 1
2 2
4 6

关键

  1. 预处理出每个数的最小质因子方便计数

代码

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<cctype>
using namespace std;

#define X first
#define Y second

typedef pair<int,int> pii;
typedef long long LL;
const char nl = '\n';
const int N = (1 << 20) + 10;
const int M = 2e5+10;
LL f[30];	
vector<int> p;
bool st[N];
int minp[N];

LL fact(int x){
	return (x == 1) ? 1 : fact(x - 1) * x;
}

void init(){	//预处理出阶乘数组还有每个数的最小质因子
	for(int i = 1; i <= 20; i ++ )f[i] = fact(i);//最多有20个
	for(int i = 2; i <= (1 << 20); i ++ ){
		if(!st[i])p.push_back(i),minp[i] = i;
		for(int j = 0; p[j] * i <= (1 << 20); j ++ ){
			st[p[j] * i] = 1;	//p[j]是质数
			minp[p[j] * i] = p[j];
			if(i % p[j] == 0)break;		//p[j]是p[j] * i的最小质因子
		}
	}
}

void solve(){
	int n;
	init();
	while(cin >> n){
		int p1,p2;
		int tot = 0,cnt = 0;
		vector<LL> v;
		while(n != 1){
			p1 = minp[n];
			n /= p1;
			cnt ++;
			p2 = minp[n];
			if(p2 != p1){
			    v.push_back(f[cnt]);
			    cnt = 0;
			}
			tot ++;
		}
		LL ans = f[tot];
		for(auto x:v)ans /= x;
		cout << tot << " "<< ans << nl;
	}	
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);

	solve();
}

注意

  1. \(2^{20}\)大概是1e6左右
posted @ 2023-03-20 22:54  Keith-  阅读(23)  评论(0编辑  收藏  举报