[素数拓展] 质因数的个数 [2007年清华大学计算机研究生机试真题]

题目描述:
求正整数N(N>1)的质因数的个数。 相同的质因数需要重复计算。如120=22235,共有5个质因数。
输入描述:
可能有多组测试数据,每组测试数据的输入是一个正整数N,(1<N<10^9)。
输出描述:
对于每组数据,输出N的质因数的个数。
样例输入:
120
样例输出:
5

解题思路: 输入值的取值规模是 1 0 9 10^9 109, 筛得的素数数目只需 1 0 5 10^5 105,这样处理的理论依据是:n至多有一个大于sqrt(n)的素因数(否则两个大于sqrt(n)的数相乘大于n)。且若1~10000内的素数都不是某输入值的素因数,那么该数的质因数一定等于其本身,且幂指数为1。
代码流程:
1.利用素数筛法得0到100000内的所有素数
2.输入n
3.依次测试步骤1中得到的素数能否整除n,若能则表明该素数为它的一个素因数。
4.不断将n除以该素数,直到不能再被整除为止,同时统计其幂指数。
5.若在完成某个素数的幂指数统计后,n为1,则表明n的所有素因数全部被分解出来。
6.若遍历、测试、分解完所有的预处理出来的素数,n仍然没有被除成1,则表明n存在一个大于100000的因子,且该因子必为其素因数,且其幂指数必为1。
7.最后,将所有素因数的幂指数相加,即得到素因数的个数。

#include<bits/stdc++.h>
using namespace std; 

bool mark[100001];//mark[x]为true,则表示该数x已被标记为非素数 
int prime[100000];//保存筛得的素数 
int primeSize;//保存已得到的素数个数 

void init(){//素数筛法 
	for(int i=0; i<=100000; i++)
		mark[i] = false;//初始化,所有数字均标记为素数
	primeSize = 0;//得到的素数个数初始为0 
	for(int i=2; i<=100000; i++){//依次遍历2到10000所有数字 
		if(mark[i]==true) continue;//若该数字已经被标记为非素数,则跳过 
		prime[primeSize++] = i;//否则,记录该素数 
		if(i>=1000) continue;//大于1000的不需要再进行标记,因为i在1000以内已经将100000以内的非素数都标记完了 
		for(int j=i*i; j<=1000; j+=i){//将该素数的所有倍数标记为 
			mark[j] = true;
		}
	}
} 

int main(){
	init();
	int n;
	while(scanf("%d", &n)!=EOF){
		int ansPrime[50]; //按顺序保存分解出的素因数
		int ansSize = 0; //分解出素因数的个数
		int ansNum[30]; //保存分解出的素因数对应的幂指数
		for(int i=0; i<primeSize; i++){//依次测试每一个素数 
			if(n%prime[i]==0){//若该素数能整除被分解的数 
				ansPrime[ansSize] = prime[i];//则该素数为其素因数
				ansNum[ansSize] = 0; //初始化幂指数为0
				while(n%prime[i]==0){
					ansNum[ansSize]++;
					n /= prime[i];
				}
				ansSize++; //素因数数量增加
				if(n==1) break; //若已被分解成1,则分解终止 
			} 
		} 
		if(n!=1){//若测试完2到100000内所有的素因数,n仍然没有被分解为1,则剩余的因数一定是一个大于100000的素因数 
			ansPrime[ansSize] = n; //记录该数
			ansNum[ansSize++] = 1;//其幂指数只能为1 
		} 
		int ans = 0;
		for(int i=0; i<ansSize; i++)
			ans += ansNum[i]; //统计各个素因数的幂指数
		cout << ans << endl;//输出 
	}
	return 0;
}

本题在线测试入口

结束


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值