算法笔记 P167 例题:【PAT A1059】Prime Factors

算法笔记练习 题解合集

题目链接

题目

Given any positive integer N, you are supposed to find all of its prime factors, and write them in the format N = p 1 k 1 × p 2 k 2 x ⋯ × p m k m N=p_1^{k_1}\times p_2^{k_2}x\dots\times p_m^{k_m} N=p1k1×p2k2x×pmkm.

Input Specification:

Each input file contains one test case which gives a positive integer N N N in the range of long int.

Output Specification:

Factor N N N in the format N N N= p 1 p_1 p1^ k 1 k_1 k1* p 2 p_2 p2^ k 2 k_2 k2* … \dots * p m p_m pm^ k m k_m km​​ , where p i p_i pi's are prime factors of N in increasing order, and the exponent k i k_i ki​​ is the number of p i p_i pi – hence when there is only one p i p_i pi​​, k i k_i ki​​ is 1 and must NOT be printed out.

Sample Input:
97532468
Sample Output:
97532468=2^2*11*17*101*1291

思路

步骤 3 和步骤 4 被整合成了质因子分解函数primeFactorization,具体实现看代码。

  1. 开素数表,判断到略大于 2 31 \sqrt{2^{31}} 231 即可;
  2. 由于 2 × 3 × 5 × 7 × 11 × 13 × 17 × 19 × 23 > 2 31 − 1 2\times3\times5\times7\times11\times13\times17\times19\times23>2^{31}-1 2×3×5×7×11×13×17×19×23>2311,所以统计因式分解结果的数组开到 10 就够了,开数组factors[10],初始化;
  3. 遍历素数表primeTable,对num进行因式分解,令n = num
    a. 当primeTable[i] > sqrt(num)时停止遍历;
    b. 若primeTable[i]能整除n,把该素数的值写入factors[i].x
    c. 不断用primeTable[i]去除n,直至不能整除,同时统计除的次数,写入factors[i].exp
  4. 遍历结束后,若n == 1,说明因式分解完毕,否则,还剩下一个大于sqrt(num)的大因子,将其信息写入factors
  5. 根据factors输出答案。

细节:

  • factors为什么要开10而不是9?因为要给步骤 4 的大因子留一个位置;
  • 需要特判输入为1的情况;
  • 在正式进行因式分解的部分,不能直接对num动手,要留副本;
  • 大数组要开成全局变量,不能开在main或者其他函数里面,否则会造成段错误。

代码

#include <stdio.h>
#include <math.h> 

#define MAX 50000

typedef struct {
	int x, exp;
} Factor; 

// 打素数表 
int isPrime[MAX], primeCnt = 0, primeTable[MAX/10];
int findPrime(void) {
	int i, j;
	for (i = 2; i < MAX; ++i)
		isPrime[i] = 1;
	for (i = 2; i < MAX; ++i) {
		if (isPrime[i]) {
			primeTable[primeCnt++] = i; 
			for (j = i; j < MAX; j += i)
				isPrime[j] = 0; 
		} 
	} 
} 

// 对 num 质因子分解,结果放入 factors,返回质因子数量 
// 要求 num >= 2 
int primeFactorization(int num, Factor *factors) {
	int i, n = num;		// n 是 num 的副本 
	int factorCnt = 0;
	for (i = 0; i < 10; ++i)
		factors[i].exp = 0;
	for (i = 0; i < primeCnt; ++i) {
		if ((int)sqrt((double)num) < primeTable[i])
			break;
		if (n % primeTable[i] == 0) {
			factors[factorCnt].x = primeTable[i];
			while (n % primeTable[i] == 0) {
				n /= primeTable[i];
				++factors[factorCnt].exp;
			}
			++factorCnt;
		}
	}
	if (n != 1) {
		factors[factorCnt].x = n;
		factors[factorCnt].exp = 1;
		++factorCnt;
	}
	return factorCnt;
} 

int main() {
	findPrime();		// 打表 
	int num, i;
	scanf("%d", &num);
	if (num == 1) {		// 特判 
		printf("1=1");
		return 0;
	}
	// 质因子分解 
	Factor factors[10];
	int factorCnt = primeFactorization(num, factors);
	// 输出 
	int flag = 0;
	printf("%d=", num); 
	for (i = 0; i < factorCnt; ++i) {
		if (flag)
			putchar('*');
		flag = 1;
		printf("%d", factors[i].x);
		if (factors[i].exp > 1) 
			printf("^%d", factors[i].exp); 
	} 
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值