Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 5130 | Accepted: 1624 |
Description
Given a positive integer X, an X-factor chain of length m is a sequence of integers,
1 = X0, X1, X2, …, Xm = X
satisfying
Xi < Xi+1 and Xi | Xi+1 where a | b means a perfectly divides into b.
Now we are interested in the maximum length of X-factor chains and the number of chains of such length.
Input
The input consists of several test cases. Each contains a positive integer X (X ≤ 220).
Output
For each test case, output the maximum length and the number of such X-factors chains.
Sample Input
2 3 4 10 100
Sample Output
1 1 1 1 2 1 2 2 4 6
题意:
给出数 X(小于等于2 ^ 20),定义 1 = X0, X1, X2, …, Xm = X,满足 Xi-1 必能整除 Xi,输出满足这样序列的最长 m 和 满足最长 m 的次数 N。
思路:
数学 + 素数筛选 + 排列组合。Xi-1 必能整除 Xi,故将 X 因式分解成一个个质因子,后求质因子的排列组合种数即可。但是TLE了 N 遍,题目给的范围是2 ^ 20,说明质因子个数最多不超过20个,所以只需要开保存质因子个数的数组到20 + 5就好。如果开到MAX长度的话,memset 会导致TLE。素数筛选也可以改进。
AC:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX ((1<<20) + 5)
typedef long long ll;
int vis[MAX],pri[MAX],sum[25]; //开25就好
ll A_num[25];
int num;
void make_pri() {
num = 0;
memset(vis,0,sizeof(vis));
vis[1] = 1;
for(int i = 2;i * i < MAX;i++) {
if(vis[i]) continue;
for(int j = i;j * i < MAX;j++) //j为倍数,从i倍开始
vis[i * j] = 1;
}
//要另外开个循环存素数,因为在上面存素数的话,只存到i * i < MAX 时候 i 前面的部分
for(int i = 2;i < MAX;i++)
if(!vis[i]) pri[num++] = i;
}
void A() {
A_num[1] = 1;
for(int i = 2;i <= 20;i++)
A_num[i] = A_num[i - 1] * i;
}
int main() {
int n;
make_pri();
A();
while(~scanf("%d",&n)) {
if(!vis[n]) printf("1 1\n");
else {
int ans = 0,s = 0;
memset(sum,0,sizeof(sum)); //数组太大会超时
for(int i = 0;i < num;++i) {
if(n == 1) break;
if(!vis[n]) {
ans++;
break;
}
if(!(n % pri[i])) s++;
while(!(n % pri[i])) {
n /= pri[i];
sum[s]++;
ans++;
}
}
ll res;
printf("%d ",ans);
res = A_num[ans];
for(int i = 1;i <= s;++i)
if(sum[i] > 1) res /= A_num[sum[i]];
printf("%I64d\n",res);
}
}
return 0;
}