题目:
http://poj.org/problem?id=3421
题意:
求n的因子链,使得前一个数整除后一个数,求出链的最大长度以及这样的链的数量。
思路:
n可以分解成质因子的乘积,n = p1^a1 * p2^a2 * p3^a2.....pn^an.
最大长度ans = a1+a2+a3...+an,
链的数量 = ans!/ a1! * a2! * ...* an!. (如果我把所有质因子都排列好,从前到后乘起来就可以看成是一条新的链。
这样的思路还是会超时严重,应该预处理得到质数表。
CODE:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const ll maxn = (1<<20)+5;
bool vis[maxn];
int pri[85000], k;
ll f[25];
ll n;
void isprime()
{
k = 0;
//memset(vis, 0, sizeof(vis));
for(int i = 2; i < maxn; ++i) {
if(vis[i]) continue;
pri[k++] = i;
for(int j = i+i; j < maxn; j+=i) vis[j] = 1;
}
}
void work()
{
int cnt, ans = 0;
ll under = 1;
for(ll i = 0; i < k; ++i) {
if(n % pri[i] == 0) {
cnt = 0;
while(n%pri[i] == 0) {
n /= pri[i];
cnt++;
}
under *= f[cnt];
ans += cnt;
}
if(n == 1) break;
if(!vis[n]) {
ans++;
break;
}
}
printf("%d %I64d\n", ans, f[ans]/under);
}
int main()
{
isprime();
f[1] = 1;
for(int i = 2; i <= 20; i++) {
f[i] = f[i - 1]*i;
}
while(~scanf("%lld", &n)) {
work();
}
return 0;
}