题目链接:http://poj.org/problem?id=3421
题目大意:给出一个正整数X,得到一个序列1 = X0, X1, X2, …, Xm = X,满足Xi<Xi+1,并且Xi是Xi+1的约数,求序列最大长度和这个长度的序列共有几条。
由条件可以知道,X0,X1...Xm均为X的约数,当序列最长的时候,每个Xi之间的倍数一定是X的素因子,
其最大长度就是所有素因子指数之和,而满足这个长度的条数就是所有素因子指数之和的阶乘除以各个素因子指数的阶乘
先素数打表,再计算给出的整数的素因子以及它们的指数,再得到阶乘计算结果。
代码:
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1100000+5;
const int maxp=10000+5;
int sum,x,k;
int prime[maxn];
bool vis[maxn];
int num[maxp];
void shai(){
sum=0;
memset(vis,true,sizeof(vis));
for(int i=2;i<maxn;i++){
if(vis[i]){
prime[sum++]=i;
}
for(int j=0;j<sum&&i*prime[j]<maxn;j++){
vis[i*prime[j]]=false;
if(i%prime[j]==0)
break;
}
}
}
ll get_len(){
ll ans=0;
for(int i=0;i<k;i++){
ans+=(ll)num[i];
}
return ans;
}
ll f(ll x){
ll res=1;
for(int i=2;i<=x;i++){
res*=i;
}
return res;
}
ll get_num(){
ll cnt=f(get_len());
for(ll i=0;i<k;i++){
cnt/=f(num[i]);
}
return cnt;
}
void solve(){
k=0;
memset(num,0,sizeof(num));
for(int i=0;i<sum;i++){
if(x%prime[i]==0){
while(x%prime[i]==0){
num[k]++;
x/=prime[i];
}
k++;
}
if(x==1)
break;
}
printf("%lld %lld\n",get_len(),get_num());
}
int main()
{
shai();
while(~scanf("%d",&x)){
solve();
}
return 0;
}