机试算法讲解:第26题 分解素因数

/*
问题:质因数个数.求正整数N(>1)的质因数的个数。相同的质因数需要重复计算。如120=2*2*2*3*5,共有5个质因数。
输入:多组测试数据,每组测试数据的输入时一个正整数N,(1<N<10^9)
输入:120
输出:5
注意:1不是N的质因数:若N为质数,N是N的质因数
思路:
用素数筛选法预先筛选出可能在题面所给定的数据范围内成为素因数的素数。程序输入待处理数字n时,依次遍历所有小于n的素数,确定为素因数后,通过试除确定对应的幂指数。
求出幂指数的和即为所求。

关键:
1 N最大为10的9次方,因此需要将素因数求到10的9次方的一般即5次方,此时质因数的的幂指数次数为
2 需要建立3个数组,第一个数组用于保存质因数,第二个数组要保存对应质因数的次数
3 它通过不断处理质因数,最终分解该数=1时,应该提前跳出做判断
4 对于如果测试100000内的所有素因数,若n仍未被分解为1,则剩余因数一定是n,大于100000的素因数
5 		if(i >= 1000)//这个是用来防止溢出,因为两个大整数相乘可能溢出。这里i>=1000时,基本后面全部筛选过了
		{
			continue;
		}
*/

#include <stdlib.h>
#include <stdio.h>

int prime[100001];
int primeSize;
bool mark[100001];//因为primeSize会累加到100001,1万没有崩溃,共申请内存40000*4B = 40*4KB = 0.16MB,100000 = 申请1.2MB内存


//建立起i与质数的关系
void init()
{
	long i ;
	primeSize = 0;
	for( i = 1 ; i <= 100000 ; i++)
	{
		mark[i] = false;//默认为素数,false
	}
	for( i = 2 ; i <= 100000 ; i++ )
	{
		if(true==mark[i])
		{
			continue;//如果是非素数直接跳过
		}
		prime[primeSize++] = i;//素数
		if(i >= 1000)//这个是用来防止溢出,因为两个大整数相乘可能溢出。这里i>=1000时,基本后面全部筛选过了
		{
			continue;
		}
		for(long j = i*i ; j <= 10000 ; j += i)//J=I*I超过65535溢出
		{
			mark[j] = true;//这里发生中断
			//printf("%d %d",i,j);
		}
	}
}

int main(int argc,char* argv[])
{
	init();
	int iNum;
	while(EOF!=scanf("%d",&iNum))
	{
		int ansNum[30];//2的30次方约为1000的3次方为10的9次方
		int iSize = 0;
		int ansSize[30];//保存每个质因数对应的次数
		for(int i = 0 ; i < primeSize ; i++)
		{
			//如果该数字能够被分解为质因数,统计相应的次数
			if(iNum%prime[i]==0)
			{
				//如果能够分解,就循环分解
				ansNum[iSize] = prime[i];
				ansSize[iSize] = 0;//易错,要先给定初始值为0
				while(iNum%prime[i]==0)
				{
					ansSize[iSize]++;
					iNum /= prime[i];
				}
				//不能分解就令
				iSize++;
				//易错,如果已经被分解为1,则终止
				if(1==iNum)
				{
					break;
				}
			}
		}
		//如果分解到最后都不成功,则说明该质因数是大于100000,并且只可能次数为1
		if(iNum!=1)
		{
			ansNum[iSize] = iNum;
			//ansSize[iSize] = 1;//易错,这里iSize还要进行累加,取下一个
			ansSize[iSize++] = 1;
		}
		//统计次数
		int iTotalCount = 0;
		for(int k = 0 ; k < iSize ; k++)
		{
			iTotalCount += ansSize[k];
		}
		printf("%d",iTotalCount);
	}
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值