入门数学(二)素数,质因数分解

素数筛选

“埃式筛法”

具体步骤:引用百度百科

求25以内的所有素数

  1. 列出2以后的所有序列:

    • 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

  2. 标出序列中的第一个素数,也就是2,序列变成:

    • 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

  3. 将剩下序列中,划掉2的倍数,序列变成:

    • 2 3 5 7 9 11 13 15 17 19 21 23 25

  4. 如果现在这个序列中最大数小于最后一个标出的素数的平方,那么剩下的序列中所有的数都是素数,否则回到第二步。

  5. 本例中,因为25大于2的平方,我们返回第二步:

  6. 剩下的序列中第一个素数是3,将主序列中3的倍数划掉,主序列变成:

    • 2 3 5 7 11 13 17 19 23 25

  7. 我们得到的素数有:2,3

  8. 25仍然大于3的平方,所以我们还要返回第二步:

  9. 现在序列中第一个素数是5,同样将序列中5的倍数划掉,主序列成了:

    • 2 3 5 7 11 13 17 19 23

  10. 我们得到的素数有:2,3,5 。

  11. 因为23小于5的平方,跳出循环.

结论:2到25之间的素数是:2 3 5 7 11 13 17 19 23。

原理当从小到大达到某数a时,如果a没有被前面步骤的数筛去,那么a一定是素数。因为,如果a不是素数,那么a一定有小于a的因子,这样在之前的步骤中a一定会被筛去。所以当枚举到a时,还没有被筛去,那么a一定为素数。

代码如下

const int maxn = 101;
int prime[maxn], pNum = 0;
bool p[maxn] = {0};
void Find_Prime(){
	for(int i = 2; i < maxn; i++){
		if(p[i] == false){
			prime[pNum++] = i;
			for(int j = i + i; j < maxn; j += i){
				p[j] = true;
			}
		}
	}
}

质因子分解

时间复杂度O(根号n)

由于每个质因子都可能出现不只一次,所以我们用结构体factor用来存放质因子及其个数,

const int maxn = 101;
struct factor{
	int x, cnt;	//x为质因子数,cnt为其个数 
}fac[maxn];

例如给你个180 求 180fac【】数组如下

fac[0].x = 2;
fac[0].cnt = 2;

fac[1].x = 3;
fac[1].cnt = 2;

fac[2].x = 5;
fac[2].cnt = 1;

因为 2 * 3 * 5 * 7 * 11 *13 *17 *19 * 23 *29 已经超过int 的范围,所有对于一个int 类型的数求他的质因数,fac【】数组只需要开到10即可。

对于任意一个数 n 来说。如果它存在除了1 和它本身之外的因子,那么一定是在sqrt(n)的左右成对出现的。而题上问是这个数的质因子,那么这个范围又会进一步缩小,对于一个整数n来说,如果它存在【2,n】范围内的质因子,要么这些质因子全部小于等于sqrt(n)要么只存在一个大于sqrt(n)的质因子,其余质因子全部小于等于sqrt(n)。

做法:枚举1~sqrt(n)范围内的所有因子p,判断p是否是n的因子。

如果p是n的因子,那么fac【】数组中增加质因子p,并初始化其个数为 0,继续除以p每次令p的个数+1,直到p不再是n的因子为止。

if(n % prime[i] == 0){
	fac[num].x = prime[i];
	fac[num].cnt = 0;
	while(n % prime[i] == 0){
		fac[num].cnt++;
		n /= prime[i]; 
	}
	num++;
}

如果p不是n的因子直接跳过。

如果在上述操作后n还>1,说明n有且只有一个大于sqrt(n) 的质因子(可能就是n本身),这时需要把这个因子+入fac数组,并令其个数为1

if(n != 1){
	fac[num].x = n;
	fac[num++].cnt = 1;
}

时间复杂度O(根号n)。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值