整数分解与筛法 X-factor Chain

题目描述

原题来自 POJ 3421

输入正整数 \(x\),求 \(x\) 的大于 \(1\) 的因子组成的满足任意前一项都能整除后一项的序列的最大长度,以及满足最大长度的序列的个数。

输入格式

多组数据,每组数据一行,包含一个正整数 \(x\)。

输出格式

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

样例

Input复制 Output复制
2 1 1
3 1 1
4 1 1
10 2 1
100 4 6

数据范围与提示

对于全部数据,\(1≤x≤2^{20}\)。

算法分析

仔细想一下,其实不难得出以下结论:

  • 一个数可以分解成\(p_1^{e_1}p2^{e_2}...p_k^{e_k}\)的形式。
  • 这个数的最大长度就是\(e_1+e_2+...+e_k\),我们令它为\(len\)。
  • 个数就是\(\frac{len!}{e_1!e_2!...e_k!}\)。

有了以上结论,那么思路也出来了:

  1. 预处理出\(1!,2!,...,20!\),存在一个\(p\)数组里。
  2. 对于每个数,对它分解质因数,求出\(len和\frac{len!}{e_1!e_2!...e_k!}\)。
#include<bits/stdc++.h>
using namespace std;
long long n;
int k = 0;
long long sum = 0;
long long p[25];
long long v[1000005];
void jc(){//预处理阶乘
	p[0] = 1;
	for(int i = 1; i<=20; i++){
		p[i] = p[i-1]*i;
	}
}
void fj(long long x){//分解质因数
	for(int i = 2; i*i<=x; i++){
		if(x%i==0){
			int cnt = 0;
			while(x%i==0){
				cnt++;
				sum++;
				x/=i;
			}
			v[++k] = cnt;
		}
		
	}
	if(x>1){
		v[++k] = 1;
		sum++;
	}
}
int main(){
	jc();
	while(cin>>n){//多组数据
		if(n==1){
			cout<<"0 1\n";
			continue;
		}
		k = 0;
		sum = 0;//重置
		fj(n);
		long long ans = p[sum];
		for(int i = 1; i<=k; i++){
			ans/=p[v[i]];
		}
		cout<<sum<<" "<<ans<<'\n';
	}
	return 0;
}
posted @ 2026-06-14 14:36  xmgene  阅读(13)  评论(0)    收藏  举报