素数分解问题是指将一个数分成多个素数之积,基本方法是:
- 先通过素数筛法,得到一批基本的素数集合;
- 对需要分解的数,不断除以素数,得到可以分解的素数及其次数;
- 如果数字很大,将所有素数都尝试分解过一遍后,发现该数字仍然没有分解为1,那么说明存在一个大于目前所有素数集合的素数,这里直接将该剩余数字作为素数。
给出牛客网上的一个经典例题:
代码:
#include <iostream>
#include <stdio.h>
#include <queue>
using namespace std;
int num[100001]; //0代表素数,1代表非素数
int sushu[10000]; //存储素数
int numSu = 0; //素数个数
int N; //输入数字个数
int inum;
queue<int> q; //记录分解得到的各个素因数对应的次数
int ans; //最终约数个数
void init()
{
for(int i=2;i<=100000;i++){
if(num[i] == 1) continue;
else{ //否则该数字为素数
numSu++;
sushu[numSu] = i; //记录素数
for(int j=i*i;j<=100000;j+=i){
num[j] = 1; //发现更多非素数
}
}
}
}
int main()
{
init();
while(cin>>N){
for(int i=1;i<=N;i++){
cin>>inum;
int tmp = inum;
while(!q.empty()){
q.pop();
}
if(tmp==1){ //对于数字1,应该特殊处理
cout<<1<<endl;continue;
}
int k=1;
while(k<=numSu){
if(tmp%sushu[k]==0){ //当存在可以整除的素数时
int cishu = 0; //
while(tmp%sushu[k]==0){
tmp/=sushu[k]; cishu++;
}
q.push(cishu); //将该次数存入队列中
}
k++;
}
if(tmp>1) q.push(1); //如果所有素数均未能将其除尽,则剩余的作为一个质数加入
//计算该数字对应的约数个数
ans = 1;
while(!q.empty()){
ans = ans * (q.front()+1);
q.pop();
}
cout<<ans<<endl;
}
}
}
这里尤其需要注意的是第三点,当给出的数字很大时,素数集合不一定能完全覆盖它,这里就需要将剩余的数作为一个新的素数加入分解式中。