大学计算机基础C语言实验习题选(1)实验4-3 循环结构-判素数 四种做法 Miller-Rabin素性测试 孪生素数(6倍数判别法) 朴素做法 朴素改进

本文主要是介绍大学计算机基础C语言实验习题选(1)实验4-3 循环结构-判素数 四种做法 Miller-Rabin素性测试 孪生素数(6倍数判别法) 朴素做法 朴素改进,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实验4-3 循环结构-判素数

编写程序sushu.c,输入一个正整数n(n>2),判断n是否为素数。

格式要求 输入:scanf("%d",&n) 输出: (1)如果n<=2,则printf(“ERROR”)
(2)如果是素数,则printf("%d是素数", n) 否则printf("%d不是素数", n)

保存,编译、运行、测试成功后将源程序文件(.c或.cpp)压缩,提交。

方法一 朴素做法

时间复杂度:O(n)
直接一个一个筛

#include<stdio.h>
int main()
{int n;scanf("%d",&n);if(n<=2){printf("ERROR");}else{bool is_prime=true;for(int i=2;i<n;i++){if(n%i==0){is_prime=false;}}if(is_prime){printf("%d是素数",n);}else{printf("%d不是素数",n);}}return 0;
}

方法二:方法一改进

时间复杂度:O(根号n)
如果是偶数,且不是2,肯定不是素数
想象因式分解。3*4=12,不必要从2一直筛到n-1,直接筛到即可
这里最好不要用sqrt函数,计算机中,平方运算所需cpu周期比根号少得多,故更快些

#include<stdio.h>
int main()
{int n;scanf("%d",&n);if(n<=2){printf("ERROR");}else if(n%2==0&&n!=2){printf("%d不是素数",n);}else{bool is_prime=true;for(int i=2;i*i<=n;i++){if(n%i==0){is_prime=false;}}if(is_prime){printf("%d是素数",n);}else{printf("%d不是素数",n);}}return 0;
}

方法三:6倍数判别法

时间复杂度:O(根号n)是松的时间复杂度,实际上比上一个快2-4倍
这里有一个数学定理:大于等于5的质素一定和6的倍数相邻
详细解答请转步知乎
如何证明大于等于5的质素一定和6的倍数相邻?
其实就是孪生质数,有兴趣的读者可以去网上搜索了解

#include<stdio.h>
int main()
{int n;scanf("%d",&n);if(n<=2){printf("ERROR");}else if(n%2==0&&n!=2){printf("%d不是素数",n);}else{int i,is_prime=1;if(n%6!=1&&n%6!=5){is_prime=0;}else{for(i=5;i*i<=n;i+=6){if(n%i==0||n%(i+2)==0){is_prime=0;}}}if(is_prime){printf("%d是素数",n);}else{printf("%d不是素数",n);}}return 0;
}

方法四:Miller-Rabin素性测试

采用了随机抽样测试的方法,实际上有可能会判不准,因为费马小定理的逆命题实际上是错的,但是其发生概率实际很低

在测试质数时,抽样法是一个非常有用的工具。下面给出一种质数判定方法:
对于待判定的整数n。设n-1=d×2s(d是奇数)。对于给定的基底a,若ad≡1 (mod n),或存在0≤r<s使a≡-1 (mod
n),则称n为以a为底的强伪质数。利用二分法,可以在O(logn)的时间内判定n是否为以a为底的强伪质数。
对于合数c,以小于c的数为底,c至多有1/4的机会为强伪质数。

如果不是随机抽样,而是抽样特殊情况——最小的几个质数,则: 如果只用2一个数进行测试,最小的强伪质数(反例)是2047,所以一个数显然不够;
如果用2和3两个数进行测试,最小的强伪质数为1373653,大于106;
如果用2,3,5进行测试,最小的强伪质数为25326001,大于2×107;
如果用2,3,5,7进行测试,最小的强伪质数为3215031751,大于3×109,已经比32位带符号整数的最大值还大了。
可见,通常只要抽取2,3,5,7这几个固定的数进行测试就能保证测试的正确性了。

适用于大数素性判断,用到了费马小定理
感兴趣的读者可以看以下两篇文章
Miller-Rabin素性测试算法详解
素数与素性测试(Miller-Rabin测试
这在ACM中有可能会遇到,杀鸡焉用牛刀,上面三种交学校的实验够用了
这里用C语言实现

#include<stdio.h>
typedef long long ll;
ll pow_mod(ll a,ll b,ll r)
{ll ans=1,buff=a;while(b){if(b&1){ans=(ans*buff)%r;}buff=(buff*buff)%r;b>>=1;}return ans;
}
ll test(ll n,ll a,ll d)
{if(n==2){return 1;}if(n==a){return 0;}if(d%2==0){d>>=1;}int t=pow_mod(a,d,n);while(d!=n-1&&t!=n-1&&t!=1){t=t*t%n;d<<=1;}return t==n-1||(d&1)==1;
}
ll isprime(ll n)
{int a[]={2,3,5,7};for(int i=0;i<=3;i++){if(n==a[i]){return 1;}if(!test(n,a[i],n-1)){return 0;}}
}
int main()
{int n;scanf("%d",&n);if(n<=2){printf("ERROR");}else if(n%2==0&&n!=2){printf("%d不是素数",n);}else{if(isprime(n)){printf("%d是素数",n);}else{printf("%d不是素数",n);}}return 0;
}

这篇关于大学计算机基础C语言实验习题选(1)实验4-3 循环结构-判素数 四种做法 Miller-Rabin素性测试 孪生素数(6倍数判别法) 朴素做法 朴素改进的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/680120

相关文章

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

C#基础之委托详解(Delegate)

《C#基础之委托详解(Delegate)》:本文主要介绍C#基础之委托(Delegate),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 委托定义2. 委托实例化3. 多播委托(Multicast Delegates)4. 委托的用途事件处理回调函数LINQ

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

使用C语言实现交换整数的奇数位和偶数位

《使用C语言实现交换整数的奇数位和偶数位》在C语言中,要交换一个整数的二进制位中的奇数位和偶数位,重点需要理解位操作,当我们谈论二进制位的奇数位和偶数位时,我们是指从右到左数的位置,本文给大家介绍了使... 目录一、问题描述二、解决思路三、函数实现四、宏实现五、总结一、问题描述使用C语言代码实现:将一个整

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

Python循环缓冲区的应用详解

《Python循环缓冲区的应用详解》循环缓冲区是一个线性缓冲区,逻辑上被视为一个循环的结构,本文主要为大家介绍了Python中循环缓冲区的相关应用,有兴趣的小伙伴可以了解一下... 目录什么是循环缓冲区循环缓冲区的结构python中的循环缓冲区实现运行循环缓冲区循环缓冲区的优势应用案例Python中的实现库