【PAT笔记】数学问题——素数和质因数

1 素数

1.1 素数的判断

素数的判断较为简单,直接上代码,需要注意的几点:

bool isPrime(int n){
    if(n==1) return false;       //1需要特判
    int sqr=(int)sqrt(n*1.0);    //之所以要用这条语句而不是在for循环里使用sqrt(n),解释如下
    for(int i=2;i<=sqr;i++){
        if(n%i==0) return false;
    }
    return true;
}

在上面的代码中,其中需要用到一条  int sqr=(int)sqrt(n*1.0); 用来在循环中做一个循环边界呢。首先可以从 double sqrt(double) 可以看出,sqrt()的返回值和参数都是double类型的。在计算机中,小数都是不精确的,如,sqrt(9)是等于3.000000000001还是2.999999999999都是不好讲的。有的计算机可能给出前者,有的则可能是后者,这样对我们循环的边界的判断造成了影响。于是就用到了上面一行代码,转化参数的数据类型,保证sqrt得到我们想要的值。

1.2 素数表的获取 

下面给出两个方法。

首先是比较常用的,对n不超过10^{^{\boldsymbol{5}}}是可以的,复杂度包括了判断是否为素数O(\sqrt{n})和遍历从1到n的复杂度O(n),因此第一种方式(对n不超过10^{^{\boldsymbol{5}}})的时间复杂度为O(n\sqrt{n}) 。下面给出代码:

const int maxn=101;
int Prime[maxn],pNum=0;    //数组Prime()存放所有的素数,pNum为素数的个数
bool p[maxn]={0};
void Find_Prime(){
    for(int i=1;i<maxn;i++){
        if(isPrime(i)==true){    //判断是否为素数
            Prime[pNum++]=i;
            p[i]=true;
        }
    }
}

其次是时间复杂度更小的一种方式,为O(n\log (\log (n))),这是一种什么原理的,我们来看:

  1. 2是素数,因此去掉所有2的倍数,如4,6,8,10,12,14,16,18,20;
  2. 3没有被前面的步骤筛去,所以3是素数,因此去掉所有3的倍数,如6,9,12,15,18;
  3. 4被前面的步骤筛去了,所以4不是素数;
  4. 5没有被前面的步骤筛去,所以5是素数,因此去掉所有5的倍数,如5,10,15,20;
  5. 6被前面的步骤筛去了,所以6不是素数; 
  6. ……

由上面可以看出,当从小到大达到达到某数n的时候,如果n没有被前面的步骤筛去,那么n就一定是素数。原理是:当n不是素数时,必然有小于n的质因数,这样在之前筛去质因数的倍数的时候就应该把n筛去了。所以,当n没有被前面步骤筛去的时候,就一定是一个素数。于是可以给出如下代码:

const int maxn=101;
int Prime[maxn],pNum;    //同样的道理,建立一个数组Prime来存放素数,pNum为苏数的个数
bool p[maxn]={0};    //素数为0,非素数为1
void Find_Prime(int n){
    for(int i=2;i<max;i++){
        if(p[i]==0){
            Prime[pNum++]=i;
            for(int j=i;j<maxn;j += i){
                p[j]=true;
            }
        }
    }
}

2 质因数的分解

质因数分解就是将一个整数n分解成若干个素数乘积的形式,如8=2\times2\times2,18=2\times2\times3\times3等等。素数的寻找上面已经讲过了,而且值得注意的是2\times3\times5\times7\times11\times13\times17\times19\times23\times29的积就已经超过了int型的上限了。

我们对于质因数的分解,不妨先设一个结构体:

struct factor{
    int x,cnt;    //x代表了质因数,cnt代表了该质因数的个数
}fac[10];

那么对于180来说,就有

fac[0].x=2;
fac[0].cnt=2;

fac[1].x=3;
fac[1].cnt=2;

fac[2].x=5;
fac[2].cnt=1;

 首先枚举1~sqrt(n)范围内所有质因子p,判断p是否为n的质因数。

const num=0;
void Find_Factor(int n){
    for(int i=0;i<10;i++){
        if(n%Prime[i]==0){
            fac[num].x=Prime[i];
            fac[num].cnt=0;
            while(n%fac[num].x==0){
                fac[num].cnt++;
                n=n/fac[num].x;
            }
            num++;
        }
    }
}

 如果在上边步骤结束后n人大于1,说明n有且仅有一个质因子(即n本身),这时需要将这个质因子加入fac数组,令其个数为1.

if(n!=1){
    fac[num].x=n;
    fac[num++].cnt=1;
}

 解释完毕

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_之桐_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值