1.题目
输入正整数 X,求 X的大于 1 的因子组成的满足任意前一项都能整除后一项的严格递增序列的最大长度,以及满足最大长度的序列的个数
输入格式
输入包含多组数据,每组数据占一行,包含一个正整数表示 X。
输出格式
对于每组数据,输出序列的最大长度以及满足最大长度的序列的个数。
每个结果占一行。
数据范围
1
≤
X
≤
1≤X≤
1≤X≤ 2^20
输入样例:
2
3
4
10
100
输出样例:
1 1
1 1
2 1
2 2
4 6
2.基本思想
算术基本定理
就是因式分解的定理,所有的整数都可以唯一分解成若干个质因子乘积的形式
筛法求素数——线性筛法(欧拉筛法)
参考文章
在O(N)的时间复杂度内,求出来1 ~ n中所有的质数,以及每一个数的最小质因子。
① 筛掉的一定是合数,且一定是用其最小质因子筛的
② 合数一定会被筛掉
这样我们就可以把所有质数找出来,而且每个和数只会被最小质因子筛,所以每个和数只会被筛一次,所以整个算法的时间复杂度为O(N)
3.代码实现
筛法求素数——线性筛法(欧拉筛法)
import java.util.Scanner;
public class Main {
static final int N = 1000010;
static int[] primes = new int[N]; // 存所有的质数
static int cnt; // 存质数的个数
static boolean[] st = new boolean[N]; // 当前数有没有被筛过 0没有被筛过 1表示筛过
public static void main(String[] args) {
get_primes(100000);
for (int i = 0; i < 20; i++) System.out.println(primes[i]); // 输出100000的前20个质数
}
private static void get_primes(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j] * i <= n; j++) {
/*
因为prime中素数是递增的,所以如果i%prime[j]!=0代表i的最小质因数还没有找到,
即i的最小质因数大于prime[j]
也就是说prime[j]就是i*prime[j]的最小质因数,于是i*prime[j]被它的最小质因数筛掉了
*/
st[primes[j] * i] = true; // 把质数的i倍筛掉
/*
如果当i%prime[j]==0时,代表i的最小质因数是prime[j],
那么i*prime[j+k](k>0)这个合数的最小质因数就不是prime[j+k]而是prime[j]了
所以i*prime[j+k]应该被prime[j]筛掉,而不是后续的prime[j+k],于是在此时break
*/
if (i % primes[j] == 0) break; // 通过最小质因子来筛
}
}
}
}
X的因子链
import java.util.Scanner ;
public class Main {
static final int N = (1 << 20) + 10;
static int[] primes = new int[N]; // 存所有的质数
static int cnt; // 存质数的个数
static int[] minp = new int[N]; // 存最小质因子
static boolean[] st = new boolean[N]; // 当前数有没有被筛过
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
get_primes(N - 1);
int[] fact = new int[30]; // 记录因子
int[] sum = new int[N]; // 存因子个数
while (sc.hasNext()) {
int x = sc.nextInt();
int k = 0, total = 0;
while (x > 1) {
int p = minp[x];
fact[k] = p;
sum[k] = 0;
while (x % p == 0) { // 分解质因数
x /= p;
sum[k]++;
total++;
}
k++;
}
long res = 1;
for (int i = 1; i <= total; i++) res *= i; // 求total的阶乘
for (int i = 0; i < k; i++) { // 多重集合的排列数
for (int j = 1; j <= sum[i]; j++) {
res /= j;
}
}
System.out.println(total + " " + res);
}
}
private static void get_primes(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) {
minp[i] = i; // 因为i是质数 最小质因子就是它本身
primes[cnt++] = i;
}
for (int j = 0; primes[j] * i <= n; j++) {
int t = primes[j] * i;
st[t] = true;
minp[t] = primes[j];
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
}