火龙信奥
  • 首页
  • 课程
  • 题库
  • 打卡
    • 代码对战
    • 快速对战
  • 题单
  • 团队
  • 荣誉墙
  • 商城
  • 登录 / 注册

数论 - 判断素数

作者: 作者的头像   huolong , 时间:2022-09-25 10:57:10 , 所有人可见, 阅读  8

数论——判断素数

1.素数的定义

+   在数学里,素数指的是大于 $1$ 的正整数中,所有只有 $1$ 和 $n$ 两个因子的数,被称作素数,也叫作质数 +   合数:大于 $1$ 的正整数里,不是质数就是合数 +   三质数:一个平方数开根之后是质数的平方数叫做三质数

2. 判断素数

2.1 判断素数方法1

我们可以想到利用素数的性质来判定素数

#include <bits/stdc++.h>
#define int long long
using namespace std;
bool isprime(int n)
{
    if(n<2) return false;
    int cnt=0;
    for(int i = 1; i <= n; i ++)
    {
        if(n%i == 0) cnt++; // 求出因子的个数
    }
    if(cnt==2) return true; // 质数必定是有且仅有两个因子的数
    else return false;
}

int main() 
{
    int x;
    while(scanf("%lld", &x)==1)
    {
        if(isprime(x)) puts("Y");
        else puts("N");
    }
    return 0;
}

这个大家都能明白吧 时间复杂度 $~O(N^2)~$

2.2 判断素数方法2

完全平方数刚刚说过

所有的合数都可以写成$x=y*z$

$a*a=b$,那么$a^2=b$ $b$是完全 平方数

根据反比例函数,可以知道对于所有的合数 $x$,$\min(y, z)$都一定小于等于$\sqrt b$,所以只用枚举到$\sqrt{b}$就可以求出答案了。

小计俩:浮点类型不稳定,使用$\sqrt 4$可能等于$1.999999$,然后枚举到 $1$ 了。所以浮点数可以加上一个$eps$。($eps$的取值范围要注意!一般取值为 $0.001$)

#define int  long long
#include <cmath>
const double eps = 0.001;
bool isprime(int x)
{

    if(x<2) return false;
    double end = 0.001 + sqrt(1. * x);
    for(int i = 2; (double)i <= end; i ++)
    {
        if(x % i == 0) return false;
    }
    return true;
}

sqrt函数 我自己手写一个看看


double sqrt(double x) // 二分

{

    if(x<0) return -1;
    double l = 0, r=1E9;
    int step=100;
    double best = -1.0;
    while(step--)
    {
        double mid=(l+r)/2;
        if(mid * mid >= x) 
        {
            best = mid;
            r = mid;
        }
        else
        {
            l = mid;
        }
    }
    return best;
}

大家注意一下,sqrt 使用的是二分手段,所以时间复杂度$~\approx O(\log N)~$。乘法只用$O(1)$就能解决。所以乘法优化:


#define int  long long
#include <cmath>
const double eps = 0.001;

bool isprime(int x)
{
    if(x<2) return false;

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

}

时间复杂度:$O(\sqrt N * T)$,T是数据的组数

还是太慢,过不了

怎么办呢?

这个时候就需要使用miller_rabin算法求解了 miller_rabin算法依赖的是费马小定理

$a^n\equiv a$

当然只有 $n$ 是质数的时候才可以 但是,费马小定理是有问题的,是一个假命题,QAQ(遗憾):cry: 统计表明,在前10亿个自然数中共有50847534个素数,而满足2n-1 ≡ 1 (mod n)的合数n有5597个 如果用费马小定理的逆命题来判断一个正整数n是不是素数,在前10亿个自然数中出错的可能性为0.011%  这个出错的可能性还是很高的,但是仍然可以用这个技巧来排除大量的合数,这种方法就是费马检测 我们可以检测前面的8~12个质数,如果有一个不满足,就返回false,全部满足返回true

这样出错概率 就只有$(\frac{11}{1000})^g$了。(g是检测质数的个数) 在 long long 范围内,经试验,不会出错

但是 有可能越界 使用__int128(洛谷的破绽,noip不允许使用)就能通过

快速乘会超时


#include <iostream>

#include <cstdio>

#include <cstdlib>

using namespace std;



typedef __int128 il;



int list[8] = {2, 3, 5, 7, 19, 37, 53,  89};



il ksc(long long x, long long y, long long z)

{

il xx = 1;

il answer = xx * x * y % z;

return answer;

// if(y == 0) return 0;

// il w = ksc(x,  y/ 2, z);

// w= (w + w) % z;

// if(y & 1)

// {

// w  = (w + x) % z;

// }

// return w;

}



long long ksm(long long x, long long y, long long z)

{

if(y == 0) return 1;

il w = ksm(x, y /2 , z);

w= ksc(w, w, z);

if(y & 1)

{

w = ksc(w, x, z);

}

return w;

}



bool miller_rabin(long long n,long  long a)

{

long long d = n -1, r = 0;

while((d & 1) == 0)

{

d  >>= 1;

r ++;

}

il x =  ksm(a, d, n);

if(x== 1) 

{

return  true;

}

for(int i  = 0; i  <r ; i ++)

{

if(x == n - 1)

{

return true;

}

x =ksc(x, x, n);

}

return  false;

}



bool isprime(long long n )

{

if(n < 2) return false;

for(int a= 0;a< 8; a ++)

{

if(n == list[a])

{

return true;

}

if(n % list[a] == 0)

{

return false;

}

if(! miller_rabin(n, list[a]))

{

return false;

}

}

return true;

}



int main()

{

long long x;

while(scanf("%lld", &x) == 1)

{

if(isprime(x))

{

puts("Y");

}

else

{

puts("N");

}

}

return 0;

}

—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com

©2026加盟我们 | 关于我们 | ACM课程 | 常见问题 | 成果墙 | 评测记录 | 浙ICP备2021013995号
在线画图 | OI WIki | 打字练习
火龙信奥
请输入登录信息


请完成安全验证
验证码底图 滑块
向右拖动滑块完成验证
请输入用户名 / 绑定的手机号码



请输入注册信息(手机号验证码注册)





验证码5分钟有效,60秒内不可重复获取,每日最多3次

微信登录

微信登录二维码

正在生成二维码...

账号已过期,请续期。
去续期

绑定手机号

📱

为了更好地保护您的账号安全,享受完整的平台服务

请您尽快绑定手机号码