数论(一)—— 质数(判断质数、分解质因数)

质数

定义:在大于1的整数中,如果只包含1和本身这两个约数,就倍称为质数或素数。

质数的判定——试除法

最暴力的写法:时间复杂度O(n)

bool is_prime(int x)
{
    if(x < 2) return false;
    for(int i = 2; i < x; i ++ )
        if(x % i == 0) return false;
    return true;
}

从定义出发,首先看这个数是不是大于2,然后看能否被除1和它本身外其它数整除。
优化
如果 d | n (d能整除n),那么 n/d | n (n除以d也能整除n)。就像 12 | 3,而12 / 3 = 4,则 12 | 4 .
可以看到,质数是成对出现的,因此我们在枚举时,只需要枚举每一对儿中较小的那个,即只需要枚举 d ≤ n/d 这样的数,即 d ≤ √n 这样的数。这样时间复杂度就可以降低到O(√n)(而且一定是√n,而不是最坏),显然是一个质的飞跃。

bool is_prime(int x)
{
    if(x < 2) return false;
    for(int i = 2; i <= x/i; i ++ )
        if(x % i == 0) return false;
    return true;
}

注意:for循环中不建议这样写:for(int i = 2; i <= sqrt(x); i ++ ),每次循环都要执行一遍循环条件,但是sqrt()这个函数比较慢;
也不建议写成 i*i <= n,当n比较接近于int的最大值时,存在溢出风险,溢出后i就会变成一个负数;
综上,推荐上面给出的写法,即 i <= x/i。

分解质因数——试除法

思路:从小到大枚举所有数(尝试x的所有因数)
概念:把一个合数分解成若干个质因数的乘积的形式,即求质因数的过程叫做分解质因数

#include<iostream>

using namespace std;

void divide(int x)
{
    for(int i = 2; i <= x/i ; i ++ )
        if(x % i == 0) //一定是质数
        {
            int s = 0;
            while(x % i == 0)
            {
                x /= i;
                s ++ ; //s为i的指数
            }
            printf("%d %d\n",i,s);
        }
        
    if(x > 1) printf("%d %d\n",x,1); //大于sqrt(x)的质因子
    puts(" ");
}

int main()
{
    int n;
    cin >> n;
    while(n -- )
    {
        int x;
        cin >> x;
        divide(x);
    }
    return 0;
}

时间复杂度:最坏:O(√n),最好:O(logn),实际一般介于二者之间
注意
1.一个很重要的性质:x中最多只包含一个大于sqrt(x)的质数(很好证明,因为如果有两个的话相乘就大于x了,这是矛盾了),所以我们枚举时可以先把小于sqrt(x)的质因子枚举出来。循环结束后,x若是大于1的,说明此时这个x就是那个大于sqrt(x)的质因子。
2.我们可能会疑问,我们要找的是n的所有的质因子,可是我们枚举的是x的所有因数,这其中会包含合数,那么会不会有问题呢?
其实是没有问题的,因为当我们枚举到 i 时,就意味着我们已经把 x 的2~i-1的所有质因子都除干净了(x/=i),也就是说我们此时的x中不含有2 ~ i -1的任何质因子了,如果满足if(x%i == 0),那么说明 i 中也一定不含2 ~ i -1的任何质因子,那么这个 i 一定是个质数。
换句话说,如果i是一个合数的话,合数可以被分解成多个质数相乘,而这多个质数一定比i小且都为x的因子,但比i小的数在之前就已经被除掉了,所以i一定是一个质数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值