PAT 甲级1059 Prime Factors

1.问题描述:

PAT 甲级1059 Prime Factors_第1张图片
题目意思是给定一个整型范围内的n求出这个n能够分解的质因数,若某一个质因子的分解个数超过一个那么使用^次方表示,比如4 = 2 * 2就要写成4 = 2 ^ 2.这样的形式。

2.算法分析:

其实这一道题目是一道纯数学知识题,首先我们要理解质因子,质数就是素数,我们需要先用线性筛筛出一定范围的素数,打个表。这里给出埃式筛法,时间复杂度为O(nlogn)

#include 
using namespace std;
typedef long long LL;
const LL maxn = 1e7 + 5;

bool prime[maxn];

int main() {
	for (LL i = 2; i < maxn; i++) {
		prime[i] = false;
	}
	for (LL i = 2; i * i < maxn; i++) {
		if (prime[i]) {
			for (LL j = i * i; j < maxn; j+= i) {
				prime[j] = false;
			}
		}
	}
	return 0;
}

这个模板比较常用,可以记下来。
至于理解这个模板的话,可以看证明方法:埃式筛素数证明
将素数打好表后,我们就可以开始找符合分解的质因数了。
首先,我们要考虑我们枚举的质因数范围。
这里给出一个数学上的结论对于一个正整数n来说,如果它存在除了1和本身之外的因数,那么一定是sqrt(n)左右成对出现的。
证明:比如15 = 3 * 5
3 和 5 这两个因数是除了1和15的因数,那么他们洽洽在sqrt(n)的左边和右边。
然后我们将这个结论进一步扩展:
对于一个正整数n来说,它除了1和本身以外还有其他因数的话,那么有两种情况:
1.因数全部存在于[2,sqrt(n)]范围内
2.因数存在于[2,sqrt(n)]范围内,但是你还是没有除断,那么就将n添加进去。
然后我们可以枚举[2,sqrt(n)]范围内进行枚举若是质数且能被n整除,将n /= i,继续判断能否除尽,继续循环,这里我使用结构体记录所有因数以及因数个数。

struct factor{
	LL x, cnt;   //x代表因子,cnt记录该因子的个数 
};

LL a = (LL)sqrt(1.0 * n);
		for (LL i = 2; i <= a; i++) {
			if (prime[i]) {
				if (n % i == 0) {
					f[num].x = i;
					f[num].cnt = 0;
					while (n % i == 0) {
						f[num].cnt++;
						n /= i;
					}
					num++;
				}
			}
			if (n == 1) break;
		} 
		if (n != 1) {
			f[num].x = n;
			f[num++].cnt = 1;
		}

3.AC代码:

#include 
using namespace std;
typedef long long LL;
const LL maxn = 1e6 + 5;

struct factor{
	LL x, cnt;   //x代表因子,cnt记录该因子的个数 
};

bool prime[maxn];

int main() {
	for (LL i = 2; i < maxn; i++) {
		prime[i] = true;
	}
	for (LL i = 2; i * i < maxn; i++) {
		if (prime[i]) {
			for (LL j = i * i; j < maxn; j+=i) {
				prime[j] = false;
			}
		}
	}
	LL n;   //需分解的数
	scanf("%I64d", &n);
	LL t = n;
	factor f[100];
	int num = 0;
	if (n == 1) printf("%lld=%lld", n,n);
	else {
		LL a = (LL)sqrt(1.0 * n);
		for (LL i = 2; i <= a; i++) {
			if (prime[i]) {
				if (n % i == 0) {
					f[num].x = i;
					f[num].cnt = 0;
					while (n % i == 0) {
						f[num].cnt++;
						n /= i;
					}
					num++;
				}
			}
			if (n == 1) break;
		} 
		if (n != 1) {
			f[num].x = n;
			f[num++].cnt = 1;
		}
		printf("%lld=", t);
		for (int i = 0; i < num; i++) {
			if (i > 0) printf("*");
			printf("%lld", f[i].x);
			if (f[i].cnt > 1) {
				printf("^%lld", f[i].cnt);
			}
		}
	}
	return 0;
}

欢迎关注ly’s Blog

你可能感兴趣的:(PAT,数论,Oj,C++,alogrithm)