C++实现质因数分解

来源:互联网 发布:监控对方手机屏幕软件 编辑:程序博客网 时间:2024/06/05 19:20

      质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除(除0以外)的数称之为素数(质数);否则称为合数。根据算术基本定理,每一个比1大的整数,要么本身是一个质数,要么可以写成一系列质数的乘积;而且如果不考虑这些质数在乘积中的顺序,那么写出来的形式是唯一的。最小的质数是2。

          质因数(或质因子)在数论里是指能整除给定正整数质数两个没有共同质因子的正整数称为互质。因为1没有质因子,1与任何正整数(包括1本身)都是互质正整数的因数分解可将正整数表示为一连串的质因子相乘,质因子如重复可以指数表示。根据算术基本定理任何正整数皆有独一无二的质因子分解式。只有一个质因子的正整数为质数。综上所述质因数分解是唯一的。

质因数分解的经典算法是:

Pollard Rho因数分解(Prime decomposition
1975年,John M. Pollard提出了第二种因数分解的方法,Pollard Rho快速因数分解。该算法时间复杂度为O(n^(1/4))。
 
分解质因数代码:
将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。
程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成: 
(1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可。
(2)如果n<>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,
 重复执行第一步。
(3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。

另外在编写程序的时候还要用到的一个定理是:
判断一个自然数是否是质数,只用看从2到根号N是否能整除N。也就是说,
一个合数的最小正因子必小于根号N。

对于上面定理的简单思考证明:

首先,约数是成对出现的。比如24,你找到个约数3,那么一定有个约数8,因为24/3=8。
然后,这对约数必须一个在根号n之前,一个在根号n之后。因为都在根号n之前的话,
乘积一定小于n(根号nX根号n=n),同样,都在根号n之后的话,乘积一定大于n。
所以,如果你在根号n之前都找不到约数的话,那么根号n之后就不会有了。

如果N (N>=2)没有小于等于根号N,大于1的约数,那么N必然是质数。
假设N不是质数,并且不含有小于等于根号N的约数。
因为N是合数,那么N必然可以写成N=p*q,并且p和q大于1。根据假设,p和q都大于根号N。那么p*q>N,矛盾

具体程序:

程序用到了cmath头文件。cmath是c++语言中的库函数,其中的c表示函数是来自c标准库的函数,math为数学常用库函数

cmath库函数列表:

C语言提供了以下的数学函数,要使用这些函数时,在程序文件头必须加入:
#include <math.h>
编译时,必须加上参数「-lm」(表示连结至数学函式库),例如「gcc -lm test.c」。
函数之自变量与传回之值型别见自变量或函数前之型别宣告。
函数已经在「math.h」或其它标头档宣告过了,因此在使用时不必再加型别宣告,例如「y=sin(x);」,不用写成「y=double sin(double x);」。
#include<iostream>
#include<cmath>
using namespace std;
void PrimeDecomposition(int k)
{
cout<<k<<"=";
if(k<2)
cout<<"不能够进行质因数分解"<<endl;
else if(k==2)
cout<<"2*1"<<endl;
else
{

for(int i=2;i<sqrt(k);i++)
{
while(k!=i)//这里用while循环是考虑到质因子中有可能有重复个i的情况
{
if(k%i==0)
{
cout<<i<<"*";
k=k/i;
}
else
break;
}
}
cout<<k<<endl;
}
}
//另外一种写法
/*void Analyse(int n)  
{  
    //首先输出等式左边部分  
    cout<<n<<" = ";  
  
    //对n进行质因数分解,应先找到一个最小的质数2  
    //如果这个质数恰好等于2,则说明分解质因素的过程结束,打印  
    if(n == 2)  
    {  
        cout<<n<<endl;  
    }  
    //n小于2时,无法进行质因素分解,提示相应信息  
    else if(n < 2)  
    {  
        cout<<"该数不可以分解质因素"<<endl;  
    }  
    else  
    {  
        //如果n>=k,但n能被k整数,则打印出k的值  
        for(int i = 2;i <= sqrt(static_cast<double>(n));i++)  
        {  
            if(n % i == 0)  //关键在于这里没有用上面的while循环了,改用i--来检测是否有重复的质因子
            {  
                n = n/i;  
                cout<<i<<"*";  
                //重复执行上一步  
                i--;  
            }  
        }  
        cout<<n<<endl;  
    }  
}  */
int main()
{
int n=90;
PrimeDecomposition(n);
return 0;
}
上面的算法效率并不高,还有改进的效率更好的算法。
1:如果追求速度的话,可以先列一个质数表数组,然后从小到大试,能少做很多尝试。用查质数表的方法会快很多
关于问题的引申:如何判断一个数是不是素数
参考:
http://bbs.csdn.net/topics/340202337
http://www.cnblogs.com/skyivben/archive/2010/07/10/1775001.html


0 0