大学计算机基础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

相关文章

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

Spring 依赖注入与循环依赖总结

《Spring依赖注入与循环依赖总结》这篇文章给大家介绍Spring依赖注入与循环依赖总结篇,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. Spring 三级缓存解决循环依赖1. 创建UserService原始对象2. 将原始对象包装成工

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

Java实现本地缓存的四种方法实现与对比

《Java实现本地缓存的四种方法实现与对比》本地缓存的优点就是速度非常快,没有网络消耗,本地缓存比如caffine,guavacache这些都是比较常用的,下面我们来看看这四种缓存的具体实现吧... 目录1、HashMap2、Guava Cache3、Caffeine4、Encache本地缓存比如 caff