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

相关文章

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

Java利用Spire.Doc for Java实现在模板的基础上创建Word文档

《Java利用Spire.DocforJava实现在模板的基础上创建Word文档》在日常开发中,我们经常需要根据特定数据动态生成Word文档,本文将深入探讨如何利用强大的Java库Spire.Do... 目录1. Spire.Doc for Java 库介绍与安装特点与优势Maven 依赖配置2. 通过替换

C# List.Sort四种重载总结

《C#List.Sort四种重载总结》本文详细分析了C#中List.Sort()方法的四种重载形式及其实现原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录1. Sort方法的四种重载2. 具体使用- List.Sort();- IComparable

C语言逗号运算符和逗号表达式的使用小结

《C语言逗号运算符和逗号表达式的使用小结》本文详细介绍了C语言中的逗号运算符和逗号表达式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习... 在C语言中逗号“,”也是一种运算符,称为逗号运算符。 其功能是把两个表达式连接其一般形式为:表达

Go语言实现桥接模式

《Go语言实现桥接模式》桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化,本文就来介绍一下了Go语言实现桥接模式,感兴趣的可以了解一下... 目录简介核心概念为什么使用桥接模式?应用场景案例分析步骤一:定义实现接口步骤二:创建具体实现类步骤三:定义抽象类步骤四:创建扩展抽象类步

GO语言实现串口简单通讯

《GO语言实现串口简单通讯》本文分享了使用Go语言进行串口通讯的实践过程,详细介绍了串口配置、数据发送与接收的代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录背景串口通讯代码代码块分解解析完整代码运行结果背景最近再学习 go 语言,在某宝用5块钱买了个

CPython与PyPy解释器架构的性能测试结果对比

《CPython与PyPy解释器架构的性能测试结果对比》Python解释器的选择对应用程序性能有着决定性影响,CPython以其稳定性和丰富的生态系统著称;而PyPy作为基于JIT(即时编译)技术的替... 目录引言python解释器架构概述CPython架构解析PyPy架构解析架构对比可视化性能基准测试测

JavaScript装饰器从基础到实战教程

《JavaScript装饰器从基础到实战教程》装饰器是js中一种声明式语法特性,用于在不修改原始代码的情况下,动态扩展类、方法、属性或参数的行为,本文将从基础概念入手,逐步讲解装饰器的类型、用法、进阶... 目录一、装饰器基础概念1.1 什么是装饰器?1.2 装饰器的语法1.3 装饰器的执行时机二、装饰器的

Java JAR 启动内存参数配置指南(从基础设置到性能优化)

《JavaJAR启动内存参数配置指南(从基础设置到性能优化)》在启动Java可执行JAR文件时,合理配置JVM内存参数是保障应用稳定性和性能的关键,本文将系统讲解如何通过命令行参数、环境变量等方式... 目录一、核心内存参数详解1.1 堆内存配置1.2 元空间配置(MetASPace)1.3 线程栈配置1.

GO语言zap日志库理解和使用方法示例

《GO语言zap日志库理解和使用方法示例》Zap是一个高性能、结构化日志库,专为Go语言设计,它由Uber开源,并且在Go社区中非常受欢迎,:本文主要介绍GO语言zap日志库理解和使用方法的相关资... 目录1. zap日志库介绍2.安装zap库3.配置日志记录器3.1 Logger3.2 Sugared