素数(prime)总结

news2024/11/25 10:24:46

素数的介绍


素数定义

质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除,换句话说就是该数除了1和它本身以外不再有其他的因数;否则称为合数。

根据算术基本定理,每一个比1大的整数,要么本身是一个质数,要么可以写成一系列质数的乘积;而且如果不考虑这些质数在乘积中的顺序,那么写出来的形式是唯一的。最小的质数是2。
                        --------360百科

一.判断一个数是否是素数(prime):

(1)暴力筛选法

思路分析

根据素数的定义,我们可以简单地想到:若要判断n是不是素数,我们可以直接写一个循环(i从2到n-1,进行n%i运算,即n能不能被i整除,如被整除即不是素数。若所有的i都不能整除,n即为素数)。

bool isprime(int n)
{
    if (n == 0 || n == 1)
        return false;
    for (int i = 2; i < n; i++)
    {
        if (n % i == 0)
        {
            return false;
            break;
        }
    }
    return true;
}

时间复杂度:O(n)

这时间复杂度一看就不咋乐观,于是我们简单优化一下。

bool isprime(int n)
{
    if (n == 0 || n == 1)
        return false;
    for (int i = 2; i <= (int)sqrt(n); i++)
    {
        if (n % i == 0)
        {
            return false;
            break;
        }
    }
    return true;
}

时间复杂度:O(sqrt(n))

优化原理:素数是因子为1和本身, 如果num不是素数,则还有其他因子,其中的因子,假如为a,b.其中必有一个大于sqrt(num) ,一个小于sqrt(num) 。所以必有一个小于或等于其平方根的因数,那么验证素数时就只需要验证到其平方根就可以了。即一个合数一定含有小于它平方根的质因子。
                                                      1

 (2)除了2和3以外,2和3的倍数都不是素数

bool isprime(int n)
{
    if (n == 0 || n == 1)
        return false;
    if (n == 2 || n == 3)
        return true;
    if (n % 2 == 0 || n % 3 == 0)
        return false;
    for (int i = 2; i <= (int)sqrt(n); i++)
    {
        if (n % i == 0)
        {
            return false;
            break;
        }
    }
    return true;
}

时间复杂度:O(sqrt(n)/2) .

(3)

首先看一个关于质数分布的规律:大于等于5的质数一定和6的倍数相邻。例如5和7,11和13,17和19等等;

证明:令x≥1,将大于等于5的自然数表示如下:

······ 6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1 ······

可以看到,不在6的倍数两侧,即6x两侧的数为6x+2,6x+3,6x+4,由于2(3x+1),3(2x+1),2(3x+2),所以它们一定不是素数,再除去6x本身,显然,素数要出现只可能出现在6x的相邻两侧。这里有个题外话,关于孪生素数,有兴趣的道友可以再另行了解一下,由于与我们主题无关,暂且跳过。这里要注意的一点是,在6的倍数相邻两侧并不是一定就是质数。

根据以上规律,判断质数可以6个为单元快进,即将方法(2)循环中i++步长加大为6,加快判断速度为什么这样呢?

证明如下:

首先我们要知道,对于一个连续的3个数,是不是一定有一个模3余0,一个模3余1,一个模3余2

我们目前已经知道了要判断的数 n = 6x+1 或 6x-1

如果我们每次增1一个一个的循环则一定会遍历下面6种数

6i-1,  6i,  6i+1,  6i+2,  6i+3,  6i+4

1.假设可以被6i,6i+2,  6i+4整除,也就是可以写成2*(3i),  2*(3i+1),  2*(3i+2),那么n一定也可以被2整除,那么n一定是个偶数,但是很明显6x-1,6x+1是奇数

2.假设能被6i+3整除,即可以写成3*(2i+1),那么n至少能被3整除,因为对于一个连续的3个数,是不是一定有一个模3余0,一个模3余1,一个模3余2,而因为6x被3整除,所以6x+1,6x-1一定不会被3整除,所以不需要考虑

最终只剩下6i-1和6i+1,只需要判断这两个就行

bool isprime(int n)
{
    if (n == 0 || n == 1)
        return false;
    if (n == 2 || n == 3 || n == 5)
        return true;
    if (n % 2 == 0 || n % 3 == 0)
        return false;
    for (int i = 5; i <= (int)sqrt(n); i += 6)
    {
        if (n % i == 0 || n % (i + 2) == 0)
        {
            return false;
        }
    }
    return true;
}

时间复杂度:O(sqrt(n)/3) .

二、筛素数

1.欧拉筛(线性筛)

复杂度O(n) 1s筛出 1e8内的所有素数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e8+10;
bool as[N+1];
int prime[N+1];
int k,n,t,cnt;
void isprime()
{
	as[0]=1;
	as[1]=1;
	
	for(int i=2;i<=N;i++)
	{
		if(!as[i]) prime[++cnt]=i;
		
		for(int j=1;j<=cnt&&i*prime[j]<=N;j++)
		{
			as[i*prime[j]]=1;
			if(i%prime[j]==0) break;
		}
	}
}
int main()
{	
	isprime();	
	cin>>n;	
	while(n--)
	{
		scanf("%d",&t);
		printf("%d\n",prime[t]);
	}
}

对于欧拉筛(线性筛),每个数只会被他自己的最小质因数筛选一次,也叫线性筛。
i ∗ prime[j] 这个数的最小值质因数就是 prime[j]

2.埃式筛

复杂度O(nlogn) 1s筛出 1e7内的所有素数

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
//ios::sync_with_stdio(false);
const int N = 1e6+10;

int as[N+1];//一个数组两用

int k,n,t,cnt;

void isprime()
{
	as[0]=1;
	as[1]=1;
	
	for(int i=2;i<=N;i++)
	{
		if(!as[i])
		{
			for(int j=i*2;j<=N;j+=i)
			{
				as[j]=1;
			}
		}
	}
	
	for(int i=1;i<=N;i++)
	{
		if(!as[i]) as[++cnt]=i;
	}
}

int main()
{
	
	isprime();
	
	cin>>n;
	
	while(n--)
	{
		scanf("%d",&t);
		printf("%d\n",as[t]);
	}
}

三、6s内求 1-n 之间的素数个数(n≤1e11)

法1: 复杂度 n^(3/4)

#include<bits/stdc++.h>
using namespace std;
  
typedef long long ll;
const ll N = 4e6+10;
const int NN = 1e6+10;
const int p = 1e9 + 7;
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
ll cnt,n,k; 
ll f[N],g[N];
void ccprime()
{
    ll i,j,m;
    for(m=1;m*m<=n;++m) f[m]=n/m-1;
    for(i=1;i<=m;++i) g[i]=i-1;
    for(i=2;i<=m;++i)
    {
        if(g[i]==g[i-1]) continue;
        for(j=1;j<=min(m-1,n/i/i);++j)
        {
            if(i*j<m) f[j]-=f[i*j]-g[i-1];
            else f[j]-=g[n/i/j]-g[i-1];
        }
        for(j=m;j>=i*i;--j)g[j]-=g[j/i]-g[i-1];
    }
}
 
 
int main()
{
   	IOS;
    while(cin>>n)
    {
        ccprime();
        cout<<f[1]<<endl;
    }
}

 法2:Meisell-Lehmer(复杂度 n^(2/3))

#include<cstdio>
#include<cmath>
using namespace std;
#define LL long long
const int N = 5e6 + 2;
bool np[N];
int prime[N], pi[N];
int getprime()
{
    int cnt = 0;
    np[0] = np[1] = true;
    pi[0] = pi[1] = 0;
    for(int i = 2; i < N; ++i)
    {
        if(!np[i]) prime[++cnt] = i;
        pi[i] = cnt;
        for(int j = 1; j <= cnt && i * prime[j] < N; ++j)
        {
            np[i * prime[j]] = true;
            if(i % prime[j] == 0)   break;
        }
    }
    return cnt;
}
const int M = 7;
const int PM = 2 * 3 * 5 * 7 * 11 * 13 * 17;
int phi[PM + 1][M + 1], sz[M + 1];
void init()
{
    getprime();
    sz[0] = 1;
    for(int i = 0; i <= PM; ++i)  phi[i][0] = i;
    for(int i = 1; i <= M; ++i)
    {
        sz[i] = prime[i] * sz[i - 1];
        for(int j = 1; j <= PM; ++j) phi[j][i] = phi[j][i - 1] - phi[j / prime[i]][i - 1];
    }
}
int sqrt2(LL x)
{
    LL r = (LL)sqrt(x - 0.1);
    while(r * r <= x)   ++r;
    return int(r - 1);
}
int sqrt3(LL x)
{
    LL r = (LL)cbrt(x - 0.1);
    while(r * r * r <= x)   ++r;
    return int(r - 1);
}
LL getphi(LL x, int s)
{
    if(s == 0)  return x;
    if(s <= M)  return phi[x % sz[s]][s] + (x / sz[s]) * phi[sz[s]][s];
    if(x <= prime[s]*prime[s])   return pi[x] - s + 1;
    if(x <= prime[s]*prime[s]*prime[s] && x < N)
    {
        int s2x = pi[sqrt2(x)];
        LL ans = pi[x] - (s2x + s - 2) * (s2x - s + 1) / 2;
        for(int i = s + 1; i <= s2x; ++i) ans += pi[x / prime[i]];
        return ans;
    }
    return getphi(x, s - 1) - getphi(x / prime[s], s - 1);
}
LL getpi(LL x)
{
    if(x < N)   return pi[x];
    LL ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;
    for(int i = pi[sqrt3(x)] + 1, ed = pi[sqrt2(x)]; i <= ed; ++i) ans -= getpi(x / prime[i]) - i + 1;
    return ans;
}
LL lehmer_pi(LL x)
{
    if(x < N)   return pi[x];
    int a = (int)lehmer_pi(sqrt2(sqrt2(x)));
    int b = (int)lehmer_pi(sqrt2(x));
    int c = (int)lehmer_pi(sqrt3(x));
    LL sum = getphi(x, a) +(LL)(b + a - 2) * (b - a + 1) / 2;
    for (int i = a + 1; i <= b; i++)
    {
        LL w = x / prime[i];
        sum -= lehmer_pi(w);
        if (i > c) continue;
        LL lim = lehmer_pi(sqrt2(w));
        for (int j = i; j <= lim; j++) sum -= lehmer_pi(w / prime[j]) - (j - 1);
    }
    return sum;
}
int main()
{
    init();
    LL n;
    while(~scanf("%lld",&n))
    {
        printf("%lld\n",lehmer_pi(n));
    }
    return 0;
}

四、判断大素数

Miller Rabin 判断一个大数是不是素数

Pollard-Rho 找出大数的最大质因子

 

 P4718 【模板】Pollard's rho 算法 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 

#include<cstdlib>
#include<cstdio>
#include<ctime>
#define li inline
#define re register
#define ll __int128
#define abs(a) ((a)>0?(a):-(a))
namespace Miller_Rabin
{
	const int Pcnt=12;
	const ll p[Pcnt]={2,3,5,7,11,13,17,19,61,2333,4567,24251};
	li ll pow(re ll a,re ll b,re ll p)
	{
		re ll ans=1;
		for(;b;a=a*a%p,b>>=1)if(b&1)ans=ans*a%p;
		return ans;
	}
	li bool check(re ll x,re ll p)
	{
		if(x%p==0||pow(p%x,x-1,x)^1)return true;
		re ll t,k=x-1;
		while((k^1)&1)
		{
			t=pow(p%x,k>>=1,x);
			if(t^1&&t^x-1)return true;
			if(!(t^x-1))return false;
		}return false;
	}
	inline bool MR(re ll x)
	{
		if(x<2)return false;
		for(re int i=0;i^Pcnt;++i)
		{
			if(!(x^p[i]))return true;
			if(check(x,p[i]))return false;
		}return true;
	}
}
namespace Pollard_Rho
{
	#define Rand(x) (1ll*rand()*rand()%(x)+1)
	li ll gcd(const ll a,const ll b){return b?gcd(b,a%b):a;}
	li ll mul(const re ll x,const re ll y,const re ll X)
	{
		ll k=(1.0L*x*y)/(1.0L*X)-1,t=x*y-k*X;
		while(t<0)t+=X;return t;
	}
	li ll PR(const re ll x,const re ll y)
	{
		re int t=0,k=1;re ll v0=Rand(x-1),v=v0,d,s=1;
		while(true)
		{
			v=(mul(v,v,x)+y)%x,s=mul(s,abs(v-v0),x);
			if(!(v^v0)||!s)return x;
			if(++t==k){if((d=gcd(s,x))^1)return d;v0=v,k<<=1;}
		}
	}
	li void Resolve(re ll x,re ll&ans)
	{
		if(!(x^1)||x<=ans)return;
		if(Miller_Rabin::MR(x)){if(ans<x)ans=x;return;}
		re ll y=x;while((y=PR(x,Rand(x)))==x);while(!(x%y))x/=y;
		Resolve(x,ans);Resolve(y,ans);
	}
	li long long check(ll x)
	{
		re ll ans=0;Resolve(x,ans);
		return ans;
	}
}
signed main()
{
	srand(time(0));
	re int t;
	scanf("%d",&t);
	long long re x,res;
	for(;t;--t)
	{
		scanf("%lld",&x);
		if((res=Pollard_Rho::check(x))^x)printf("%lld\n",res);
		else printf("Prime\n");
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/154270.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux 文件夹多用户共享 解决文件删除的Permission denied

linux文件属性基础 Linux文件属主和属组 通过命令ls 可以查看文件属性&#xff1a; zcargo-MS-7D53:~/Desktop/parent_ceshi$ ll -lh total 16K drwxrwxr-x 2 zc zc 4.0K 1月 10 13:59 ceshi/ drwxrwxr-x 2 zc zc 4.0K 1月 10 13:59 ceshi02/以上展示命令的意思&#xff1…

大数据概念及Hadoop介绍

大数据概念及Hadoop介绍大数据概念数据存储单位大数据定义大数据的特点(5V特征)大数据部门组织架构分布式技术负载均衡故障转移伸缩性分布式技术总结分布式和集群的区别Hadoop介绍Hadoop核心组件Hadoop发展简史Hadoop特性优点与行业应用Hadoop特性优点行业应用Hadoop发行版本及…

14、Java网络编程

一、 网络编程概述Java是 Internet 上的语言&#xff0c;它从语言级上提供了对网络应用程序的支持&#xff0c;程序员能够很容易开发常见的网络应用程序。Java提供的网络类库&#xff0c;可以实现无痛的网络连接&#xff0c;联网的底层细节被隐藏在 Java 的本机安装系统里&…

【广度优先搜索遍历 + 染色法】判断二分图

还记得当时才大一&#xff0c;上离散数学课&#xff0c;当时觉得很不屑&#xff0c;就是觉得这学的什么玩弄啥用没有&#xff0c;但是其实很多的算法思想在解决题目时很有价值。 本文就将使用染色法解决判断二分图问题&#xff0c;使用广度优先搜索遍历和 Java 语言实现 一、题…

车辆逆行识别检测系统 opencv

车辆逆行识别检测系统通过opencvyolo网络深度学习技术&#xff0c;对现场画面中车辆逆向行驶行为进行检测抓拍预警。 OpenCV的全称是Open Source Computer Vision Library&#xff0c;是一个跨平台的计算机视觉处理开源软件库&#xff0c;支持与计算机视觉和机器学习相关的众多…

嵌入式 LINUX 驱动开发 day02 字符设备驱动 字符设备驱动 虚拟串口, 一个驱动支持多个设备

1. 驱动开发 字符设备驱动 代码&#xff1a; vser.c #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h>#include <linux/fs.h> /***** 设备相关信息 ******/ static unsigned int VSER_MAJOR 256; //主设备号…

青铜到王者,9本最好的Python从入门到进阶的书

春节长假还有2周了&#xff0c;是时候囤一些书充充电了&#xff01;新的一年群里很多小伙伴开始想学Python&#xff0c; 无论是准备转行的&#xff0c;还是想多学一份技能提高职场竞争力的&#xff0c;都想选择Python赛道&#xff0c;下面给大家推荐一些非常不错的Python入门到…

【Flask框架】—— 30 Flask-RESTful

前后端分离和前后端不分离 前后端不分离 在前后端不分离的应用模式中&#xff0c;前端页面看到的效果都是由后端控制&#xff0c;由后端渲染页面或重定向&#xff0c;也就是后端需要控制前端的展示&#xff0c;前端与后端的耦合度很高。 这种应用模式比较适合纯网页应用&…

iclr 2022 Compositional attention: Disentangling search and retrieval

Mittal S, Raparthy S C, Rish I, et al. Compositional attention: Disentangling search and retrieval[J]. arXiv preprint arXiv:2110.09419, 2021. 目录Mittal S, Raparthy S C, Rish I, et al. Compositional attention: Disentangling search and retrieval[J]. arXiv p…

【Kettle报错】kettle7.0链接MySQL显示:No appropriate protocol

【Kettle7.0链接本地MySQL数据库报错】 1. 问题描述 报错问题&#xff1a;kettle7.0报错&#xff0c;提示No appropriate protocol (protocol is disabled or cipher suites are inappropriate) 错误原因&#xff1a; Caused by: javax.net.ssl.SSLHandshakeException: No a…

Vue实现路由(Vue-router,参数传递,编程式路由导航)

目录 路由是什么&#xff1f; 怎么实现路由 第一步 创建一个文件夹 router &#xff0c;里面创建一个index.js 内容是 第二步 在main.js中引入和应用 router 第三步 在Vue中 通过两个标签进行配置 跳转路由时的参数传递 query params query参数和 param参数的区别 编…

原型链和JSON

对象的封装、继承和多态 封装、继承和多态是面向对象编程的三大特征&#xff0c;在JavaScript中也可以使用这些特征来实现面向对象的的编程。 封装是指将对象的属性和方法封装在对象内部&#xff0c;只提供必要的接口给外部访问。封装可以让我们隐藏对象的实现细节&#xff0c;…

项目管理:制定项目进度计划的好处有哪些?

项目管理计划确定了项目执行、监控及结束项目的整个过程&#xff0c;在项目开始之前&#xff0c;如能制定清晰的计划&#xff0c;并让项目成员都了解项目的目标和自己的责任&#xff0c;会对项目的推进有很大的帮助。 制定项目进度计划的好处有哪些&#xff1f; 1、目标导向…

高级树结构之二叉查找树

文章目录一 二叉查找树简介二 创建和插入操作三 查找操作3.1 查找思路3.2 代码实现四 删除操作4.1 情况讨论4.2 代码实现五 完整代码5.1 二叉查找树的结构5.2 完整代码内容一 二叉查找树简介 二叉查找树【二叉搜索树或是二叉排序树】 左子树中所有结点的值&#xff0c;均小于其…

(十一)devops持续集成开发——jenkins流水线发布一个docker harbor仓库版的前端vue项目

前言 本节内容&#xff0c;我们使用jenkins的流水线功能发布一个docker harbor私服仓库版的前端vue项目&#xff0c;延续前一节的内容&#xff0c;这里需要我们事先安装好一个docker harbor仓库用来存放我们项目的镜像&#xff0c;前端项目依然是通过nginx基础镜像构建&#x…

关于时间复杂度什么是时间复杂度

文章目录简介常见的Big-Oh简介 精确的考虑程序运行时间会使得寸步难行&#xff0c;而且毫无意义&#xff0c;所以可以用一种“概量”的概念来衡量运行时间&#xff0c;称之为“时间复杂度”。 时间复杂度的定义&#xff1a; 在一个完全立项状态下的计算机中&#xff0c;我们定…

【Sql Server】数据库的表变量和临时表的区别,并通过变量表随机生成姓名

作者&#xff1a;小5聊 简介&#xff1a;一只喜欢全栈方向的程序员&#xff0c;欢迎咨询&#xff0c;尽绵薄之力答疑解惑 公众号&#xff1a;有趣小馆&#xff0c;一个有趣的关键词回复互动功能 效果 1、表变量 1.1、表变量基本信息 1&#xff09;表变量本质是一个变量 是SQ…

《啊哈算法》第一章典例+解析+代码

目录 一&#xff0c;计数排序 二&#xff0c;冒泡排序&#xff08;Bubble Sort&#xff09; 三&#xff0c;快速排序&#xff08;Quick Sort&#xff09; 四&#xff0c;桶排序&#xff08;Bucket Sort&#xff09; 五&#xff0c;小哼买书 从无到有掌握最基础的算法 多学…

react hooks 封装一个countDown 倒计时组件

开发技术 react , hooks , ts , taro 需求分析 需要一个可以按天&#xff0c;时&#xff0c;分和秒来进行倒计时的组件。 简单使用 注&#xff1a;主要逻辑请看 useCountDown import CountDown from /components/countDown; import { useEffect, useState } from react; i…

东宝商城项目(二)——flask-script模块、flask-migrate模块和项目日志配置

学习flask-script模块的使用 1、什么是flask-script flask-script是flask的一个扩展模块&#xff0c;Flask-Script的作用是可以通过命令行的形式来操作Flask。 2、安装flask-script pip install flask-script 3、flask-script的使用 例如有这样一种需求&#xff1a; 我们…