C语言:素数筛法与分解素因数

一、素数筛法

素数筛法是关于求小于某个大数(正整数)的所有素数的算法,首先有理论:任何整数n≥2都可以分解成若干质数的乘积,即n=p1p2···pr。

用筛法求 素数的基本思想是:把从1开始的、某一范围内的 正整数从小到大顺序排列, 1不是素数,首先把它筛掉。剩下的数中选择最小的数是素数,然后去掉它的 倍数。依次类推,直到筛子为空时结束。如有:
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
1不是素数,去掉(编者注:可以直接从2开始)。剩下的数中2最小,是素数,去掉2的倍数,余下的数是:
3 5 7 9 11 13 15 17 19 21 23 25 27 29
剩下的数中3最小,是素数,去掉3的倍数,如此下去直到所有的数都被筛完,求出的素数为:
2 3 5 7 11 13 17 19 23 29(摘自百度百科~~)
用算法描述为:

int prime[100000];								//存放素数
int mark[100000];								//标记脚标表示的数字是否是素数
int prime_size;									//素数的个数

void init()
{//素数筛选函数
	prime_size =0;
	for (int i = 0; i < 100000; i++)			//标记数组初始化
		mark[i]=false;
	for (int i = 2; i < 100000; i++)
	{
		if(mark[i]==true) continue;				//若是素数则跳过
		else									//非素数
		{
			prime[prime_size++] = i;			//将该素数存入数组
			for (int j = i; j < 100000; j+=i)	//标记该素数的倍数为非素数
				mark[j]=true;
		}
	}
}
在主函数中调用init()函数,就可以较为迅速的将1~100000之间的所有素数保存于数组prime中,prime_size记录的是素数的个数

二、分解素因数(一道研究生上机试题)

题目描述:
求正整数N(N>1)的质因数的个数。
相同的质因数需要重复计算。如120=2*2*2*3*5,共有5个质因数。
输入:

可能有多组测试数据,每组测试数据的输入是一个正整数N,(1<N<10^9)。

输出:

对于每组数据,输出N的质因数的个数。

样例输入:
120
样例输出:
5
提示:

注意:1不是N的质因数;若N为质数,N是N的质因数。


思路分析:

求N的质因数个数,可以按2,3,4,5.,6..这样去试探是否能够整除(比如最开始试探2,则N会一直整除2,直至不能除尽,因此不用担心后面的序列4,6等会被计为素数),需要注意的是,如果将试探上限设置到N,会导致超时,将试探上线设置为“sqrt(N)+1”即可,因为对N的质因数序列,至多只能包含一个大于sqrt(N)的因数(若有2个,则二者之积必大于N,矛盾)。

int main()
{
	int n;
	int factor_size;
	int sqrnum,inputnum;

	while (scanf("%d",&n)!=EOF)
	{
		factor_size=0;
		sqrnum = (int)sqrt(double(n));
		int i =2;
		while (n>1)
		{
			if (n%i==0)						//i为n的素因数
			{
				factor_size++;
				n/=factor_size;
			}
			else
			{
				i++;
				if (i>sqrnum)
				{
					factor_size++;
					break;
				}
			}
		}
		printf("%d\n",factor_size);
	}return 0;

}

另一思路:利用前面素数筛法求出的素数,可以减小试探域,只用prime数组中的素数去试探,该算法其实是做了前期工作,在整体上比上面的思路的实效好好写,尤其是在输出大数时更明显。

int main()
{
	int n;
	init();
	int factor_size;
	int factor[50];
	int factor_value[50];
	int sqrnum,inputnum;

	while (scanf("%d",&n)!=EOF)
	{
		factor_size=0;
		inputnum = n;
		sqrnum = (int)sqrt(double(n))+1;

		for (int i = 0; i < 50; i++)
			factor[i]=0;
		for (int i = 0; i < prime_size&& prime[i]<sqrnum; i++)
		{
			if(n%prime[i]==0)
			{
				while (n%prime[i]==0)					//当prime[i]为n的因数时
				{
					factor[factor_size]++;
					factor_value[factor_size]=prime[i];
					n/=prime[i];
				}
				factor_size++;
				if(n==1) break;							//n被除至1,退出循环
			}
		}

		if(n>1)											//n仍未被分解至1,则剩余的因数一定是大于100000的素因数,其值就是现在的n
		{
			factor[factor_size]++;
			factor_value[factor_size++]=n;
		}
		int ans=0;
		for (int i = 0; i < factor_size; i++)
			ans += factor[i];
		printf("%d\n",ans);
	}
	return 0;
}
黑框运行结果:







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值