X的因子链 算术基本定理 素数 线性筛 分解质因数多重排列组合问题

AcWing 1295. X的因子链
在这里插入图片描述

2
3
4
10
100

输出样例

1 1
1 1
2 1
2 2
4 6

算术基本定理(公理)

每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。

⭐ 合数是可以分解成两个小的质数相乘,所以 所有因子都取 质数,符合尽可能小的题意

多重组合排列

import java.util.Scanner;

public class Main
{
	static int N = 2000010;
	static int[] p = new int[N];// 存质数
	static int[] minp = new int[N];// 存 i 对应的最小质因子
	static boolean[] st = new boolean[N];
	static int cnt;

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		getPrimes(N - 1);

		int[] fact = new int[3000];// 记录 x 的所有质因子
		int[] sum = new int[N];// 记录某个质因子的次幂(个数)
		while (sc.hasNext())
		{
			int x = sc.nextInt();
			int k = 0;// 记录 factor 因子 的个数(去重)
			int total = 0;// 总因子个数(可重复)

			while (x > 1)
			{
				int p = minp[x];// 找出 x 的最小质因子
				fact[k] = p;
				sum[k] = 0;
				while (x % p == 0)// 分解质因子
				{
					x /= p;
					sum[k]++;
					total++;
				}
				k++;
			}
//			多重排列组合问题
			long res = 1;
//			n! (n 是总因子数)
			for (int i = 1; i <= total; i++)
				res *= i;

//			n! / a! / b!/ …… (a,b,……是每个因子的个数 (次幂) )
			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 getPrimes(int n)
	{
		for (int i = 2; i <= n; i++)
		{
			if (!st[i])
			{
				p[cnt++] = i;
				minp[i] = i; // 质数的最小质因子就是它本身
			}

//			筛素数(此方法保证了合数一定会被它的最小质因子筛掉)
			for (int j = 0; p[j] <= n / i; j++)
			{
				int t = p[j] * i;
				st[t] = true;
				minp[t] = p[j];
				if (i % p[j] == 0)
					break;
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值