怎样求素数与其相关(基本)

我们经常可能会遇到这样的题目,它要求我们求出100以内的素数表,或者说给定一个数,得到它的质因子乘积和,比如,
6=2* 3,8=2* 2* 2等等,这里的2以及3,就都是素数,要想解决这类问题,就不可避免地要实现求素数这个程序,下面就来具体讲解一下。

一般求素数:
思路:对每一个数进行判断,判断是素数返回一个值,不是的话再返回另一个值,故这里有一个判断函数,另外还要有一个包装素数的函数,即若一个数是素数,则把它送到一个特定的数组里面,方便输出。
另外还要知道,1不是素数,应列为特殊情况。
具体实现代码如下:

#include <cstdio>
#include <math.h>
int prime[50],p=0;
bool is_prime(int n)//判断函数 
{
	if(n<=1)
	{
		return false;
	}
	for(int i=2;i<=sqrt(n);i++)
	{
		if(n%i==0)
		{
			return false;
		}
	}
	return true;
}
void F_prime()//封装函数 
{
	for(int i=1;i<=100;i++)
	{
		if(is_prime(i)==true)
		{
			prime[p++]=i;//如果是素数,则送入prime数组 
		}
	}
}
int main()
{
	F_prime();//不要忘了调用封装函数 
	for(int i=1;i<=p-1;i++)
	{
		printf("%d ",prime[i]);
	}
	return 0; 
}

【注意点】:有的人可能会试图将两个函数融合为一个函数,这是可行的,不过相对更容易出现错误,一般情况下选择两个独立函数求素数比较好。另外,这种方法求素数的时间复杂度为 O(n*n^(1/2)),这种方法对n小于10000的情况下来说没有问题,但若是更大的n值就有必要改进算法。

改进版求素数:
思路:不管要求多少个素数,只要是从1开始枚举,我们就可以肯定 2 一定是素数,那么既然 2 是素数,那么它的倍数 2,4,6,8等所有比n小但却是2的倍数的就都不是素数,我们可以把这些不符合条件的数筛选出去,从而减少了运算量。
代码如下:

#include <cstdio>
const int maxn=10001;//这里的maxn设为10001,它在n小于17000左右以下的数都能求得素数表,如需要还可增大maxn的值
int prime[maxn],p=0;
bool flag[maxn];
void Q_prime(int n)
{
	for(int i=2;i<n;i++)
	{
		if(flag[i]==false)
		{
			prime[p++]=i;
		}
		for(int j=2*i;j<n;j+=i)
		{
			flag[j]=true;
		}
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	Q_prime(n);
	for(int i=0;i<p;i++)
	{
		printf("%d ",prime[i]);
	}
 return 0;
}

【注意点】这种方法求素数的时间复杂度为 O(nloglogn),相对上个来说改进了一些,当然还有更加高效的算法,但不属于初学者范畴,以后有机会可以了解。

好了,学习完求素数的方法,对于给定一个数,求质因子乘积的问题你还有没有思路呢?让我们共同来探讨一下:

一个例子:8=2* 2* 2以及180=2* 2* 3* 3* 5 ;
可以看到,分解出的质因子都是从2开始,这是素数表中最小的一个素数,当然也并不排除从3或者从5开始的情况,但至少我们应该从2开始枚举,在哪里枚举?当然是在素数表里。
另外,如果一个素数满足,怎么知道它需要多少个?例如180中,2需要两个,3也需要两个,5需要一个,我们可以这样,从2开始枚举,如果满足,怎样才算满足?180%2=0就是满足,如果2满足就除以2,即180/2,得到90,继续判断2是否满足,可见90%2=0,依然满足,之后90/2=45,45%2!=0,故2不再满足,故得到满足条件的2只有两个,之后判断下一个素数3。就是这么一个过程,我们可以把它设计成一个函数。
素数表的范围怎样选取?一般来说,素数表的上限不会太大,不过还有一种特殊的情况需要注意,那就是素数的质因子分解就是它本身,例如97=97;以及不是素数的1=1;这些都需要进行特殊判断。

具体完整代码如下,请好好体会:

#include <cstdio>
#include <math.h>
const int maxn=100001;
int prime[maxn],p=0;
bool is_prime(int n)//素数判断函数 
{
	if(n<=1)
	{
		return false;
	}
	for(int i=2;i<=sqrt(n);i++)
	{
		if(n%2==0)
		{
			return false;
		}
	}
	return true;
}
void F_prime()//素数封装函数
{
	for(int i=1;i<=maxn;i++)
	{
		if(is_prime(i)==true)
		{
			prime[p++]=i;
		}
	}
}
struct factor{
	int x;
	int cont;
}fac[10];//构造一个结构体,x是质因子,cont是它的个数 
int main()
{
	F_prime();//封装完成,可以开始枚举 
	int n,num=0;//num是不同质因子的个数,与相同质因子的个数cont区分开 
	scanf("%d",&n);
	if(n==1)//判断等于1的特殊情况 
	{
		printf("1=1");
		return 0;
	}
	printf("%d=",n);
	for(int i=0;i<=sqrt(n);i++)
	{
		if(n%prime[i]==0)//该素数满足 
		{
			fac[num].x=prime[i];//记录该质因子 
			fac[num].cont=0;
			while(n%prime[i]==0)//求cont的个数 
			{
				fac[num].cont++;
				n/=prime[i];
			}
			num++;
		}
		if(n==1)
		{
			break;
		}
	}
	if(n!=1)
	{
		fac[num].x=n;
		fac[num++].cont=1;//注意这里是num++,这里是为了保证下面的for循环不管怎样都至少能循环一次 
	}
//	for(int i=0;i<num;i++)//下面编写了两种输出方式,可以根据情况自由选取 
//	{
//		if(i>0)
//		{
//			printf("*");
//		}
//		printf("%d",fac[i].x);
//		if(fac[i].cont>1)
//		{
//			printf("^%d",fac[i].cont);
//		}
//	}
	for(int i=0;i<num;i++)
	{
		if(i>0)
		{
			printf("*");
		}
		printf("%d",fac[i].x);
		while(fac[i].cont>1)//已经计数过一次,故这里减一次 
		{
			printf("*%d",fac[i].x);
			fac[i].cont--;
		}
	}
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值