您的位置:首页 > 编程语言 > C语言/C++

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

2018-01-30 23:35 302 查看
一、素数筛法

素数筛法是关于求小于某个大数(正整数)的所有素数的算法,首先有理论:任何整数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;
}
黑框运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: