Erathothenes、Jacobi_Symbol计算

2024-01-22 10:59

本文主要是介绍Erathothenes、Jacobi_Symbol计算,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实验报告

实验目的

  1. 通过编程实现对Erathothenes筛法的熟悉和掌握
  2. 通过编程实现对jacobi_symbol计算的熟悉和掌握

实验环境

代码编辑软件:VSCODE
语言:C++、cppStandard: c++17、编译器:mingw64-GCC

Eratosthenes筛法

实验原理

古希腊数学家Eratosthenes(276~194 BC)所提出的一种方法, 给出要筛数值的范围n,找出以内的素数。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个质数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个质数5筛,把5留下,把5的倍数剔除掉;不断重复下去。能够生成所有 ≤ N ≤N N的素数表, 直到2004年才被改进。改进版本的核心思想是若 n ≤ N n≤N nN且n是合数,则n必有一不大于 N \sqrt{N} N 的素因子。最佳筛法的伪码表在这里插入图片描述根据伪码表示的提示,在实际编码中,既要考虑程序的正确性,又要考虑程序的计算开销和存储开销,我们有以下优化算法的启发:

  1. 在筛选素数的过程中,设置一个bool型的数组对计算和存储开销较方便控制,以0、1来记录是否为素数
  2. 若i不是素数,可以不剔除其倍数,其倍数已经被其因数剔除
  3. 不必从 i ∗ 2 i*2 i2开始筛,在 i = 2 i=2 i=2时筛过;也不必在 i ∗ 3 i*3 i3时开始…;不必从 i ( i − 1 ) i(i-1) i(i1)时开始;因为在2、3的时候就已经被筛选过了,就从 i ∗ i i*i ii开始

实验过程

  1. 将通过C++代码的具体编写实现对Eratosthenes算法的理解
  2. 通过设置对比实验,从计算时间上观测时间上最优的Eratosthenes相比于初始Eratosthenes的改进效果
  3. 引入vector简化编码

代码

#include <iostream>  
#include <vector>  
#include <cmath>  
#include <ctime>
using namespace std;// 书上的最优化的Eratosthenes算法  
vector<long> sieveofEratosthenes(long n) {clock_t start,end;start = clock();// 确认素数vector<bool> isPrime(n + 1, true); // 初始化所有数均为素数,直接标记2-n,索引从0开始,为n+1  long m = sqrt(n); // 只需要筛选到sqrt(n)即可  for (long i = 2; i <= m; i++) { // 从2开始,将它的倍数都标记为非素数  if (isPrime[i]) { // 首先确认是否是素数,再用素数筛倍数for (long j = i * i; j <= n; j += i) {isPrime[j] = false;}}}end = clock();cout<<"sieve of Eratosthenes timeclock is: "<<double(end-start)<<"ms"<<endl;// 记录素数vector<long> primes;for (long i = 2; i <= n; i++) {if (isPrime[i]) {primes.push_back(i); }}return primes;
}vector<long> easyEratosthenes(long n) {// 确认素数clock_t start,end;start = clock();vector<bool> isPrime(n + 1, true); // 初始化所有数均为素数,直接标记2-n,索引从0开始,为n+1   for (long i = 2; i <= n; i++) { // 从2开始,将它的倍数都标记为非素数  for (long j = i * 2; j <= n; j += i) {isPrime[j] = false;}}end = clock();cout<<"easyEratosthenes timeclock is: "<<double(end-start)<<"ms"<<endl;
}int main() {long n;cout << "input the n:" << endl;cin >> n;vector<long> primes = sieveofEratosthenes(n);easyEratosthenes(n);/*for (long prime : primes) {cout << prime <<" "<< endl;    }return 0;*/
}

实验结果

在这里插入图片描述
在这里插入图片描述结果分析,时间上最优的筛法和最原始的筛法,在结果上是完全正确的且一致的,但是在计算速度上差距甚大,在10000000的时候差距接近1:5.5。但是由于代码为了便于编写使用了vector函数,若使用最简单的数组来做,运行速度和存储效率可能还对提升,但这不是这次实验的主要目的。

Jacobi_symbol的计算

引入雅可比符号,正是因为计算勒让德符号时,需要把 n n n分解成标准分解式,这常常时很麻烦的,这也是运用勒让德符号进行计算时的缺点,避开这个缺点,就是引入雅可比符号,它的计算法则,容易由勒让德符号的性质推出。

实验原理

  1. 定理一:
    n ≡ n 1 ( m o d m ) 和 ( n , m ) = 1 n≡n_1(mod m)和(n,m)=1 nn1(modm)(n,m)=1,则
    ( n / m ) = ( n 1 / m ) (n/m)=(n_1 /m) (n/m)=(n1/m)
    ( n , m ) = ( n , m 1 ) = 1 (n,m)=(n,m_1)=1 (n,m)=(n,m1)=1,则
    ( n / m ) ( n / m 1 ) = ( n / m m 1 ) (n/m)(n/m_1)=(n/mm_1) (n/m)(n/m1)=(n/mm1)
    若(n,m)=(n_1,m)=1,则
    ( n / m ) = ( n 1 / m ) = ( n n 1 / m ) (n/m)=(n_1/m)=(nn_1/m) (n/m)=(n1/m)=(nn1/m)
  2. 定理二:
    ( − 1 / m ) = ( − 1 ) ( m − 1 ) / 2 (-1/m)=(-1)^{(m-1)/2} (1/m)=(1)(m1)/2
  3. 定理三:
    ( 2 / m ) = ( − 1 ) m 2 − 1 (2/m)=(-1)^{m^2-1} (2/m)=(1)m21
  4. 定理四:互反律
    m m m n n n是第二个正奇数,则 ( n , m ) = 1 (n,m)=1 (n,m)=1,则
    ( m / n ) ( n / m ) = ( − 1 ) ( m − 1 ) ( n − 1 ) / 4 (m/n)(n/m)=(-1)^{(m-1)(n-1)/4} (m/n)(n/m)=(1)(m1)(n1)/4

分析,利用以上定理即可计算雅可比符号,这是柯召《数论讲义》上的定理,上述定理经过某些推导可产生更具体的结论,下面这套:

  1. 如果 n n n是一个正奇数,则 m 1 ≡ m 2 ( m o d n ) m_1≡m_2 (mod n) m1m2(modn),那么
    ( m 1 / n ) = ( m 2 / n ) (m_1/n)=(m_2/n) (m1/n)=(m2/n)
  2. 如果 n n n是一个正奇数,那么
    ( 2 / n ) = 1 n ≡ ± 1 ( m o d 8 ) ; ( 2 / n ) = − 1 n ≡ ± 3 ( m o d 8 ) (2/n)=1 n≡±1(mod 8);(2/n)=-1 n≡±3(mod 8) (2/n)=1n±1(mod8)(2/n)=1n±3(mod8)
  3. 如果 n n n是一个正奇数,那么
    ( m 1 m 2 / n ) = ( m 1 / n ) ( m 2 / n ) (m_1m_2/n)=(m_1/n)(m_2/n) (m1m2/n)=(m1/n)(m2/n)
    特别地,如果 m = 2 k t m=2^kt m=2kt t t t为一个奇数,那么
    ( m / n ) = ( 2 / n ) k ( t / n ) (m/n)=(2/n)^k(t/n) (m/n)=(2/n)k(t/n)
  4. 如果 m m m n n n是正奇数,那么
    ( m / n ) = − ( n / m ) m ≡ n ≡ 3 ( m o d 4 ) , ( m / n ) = ( n / m ) 其他 (m/n)=-(n/m) m≡n≡3(mod 4),(m/n)=(n/m) 其他 (m/n)=(n/m)mn3(mod4)(m/n)=(n/m)其他

实验过程

通过C++编写实现对雅可比符号的计算,然后验证雅可比符号计算的正确性,由于上述实验原理本质相同,在算术上的改进效果甚微,因此在本代码的编写中考虑到计算的特征,准备对雅可比符号的计算函数设计嵌套模式。

代码

#include <iostream>  
using namespace std;  int jacobiSymbol(int a, int n) {if (a == 0) {return 0;}if (a == -1){if((n-1)%2) return 1;else return -1;}if (n == 1) {return 1;}if (a % 2 == 0) { //定理三应用int k=(n^2-1)%8;if (k%2 == 0) return jacobiSymbol(a/2,n);else return -jacobiSymbol(a/2, n);}if (a<n && n % 2 == 1 && a % 2 == 1) {int zf = ((a-1)*(n-1))/4;              // 互反正负标识位if (zf%2) return jacobiSymbol(n, a);else return -jacobiSymbol(n,a);}if (a>n) {  a = a % n; return jacobiSymbol(a, n);}
}int main() {  int a, n;  cout << "Enter the value of a: ";  cin >> a;  cout << "Enter the value of n which must be the odd integer: ";  cin >> n;  int result = jacobiSymbol(a, n);  cout << "The Jacobi_symobol is "<<result<<endl;return 0;  
}

实验结果

在这里插入图片描述
结果表明,雅可比符号计算具有正确性

这篇关于Erathothenes、Jacobi_Symbol计算的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

XTU 1237 计算几何

题面: Magic Triangle Problem Description: Huangriq is a respectful acmer in ACM team of XTU because he brought the best place in regional contest in history of XTU. Huangriq works in a big compa

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

GPU 计算 CMPS224 2021 学习笔记 02

并行类型 (1)任务并行 (2)数据并行 CPU & GPU CPU和GPU拥有相互独立的内存空间,需要在两者之间相互传输数据。 (1)分配GPU内存 (2)将CPU上的数据复制到GPU上 (3)在GPU上对数据进行计算操作 (4)将计算结果从GPU复制到CPU上 (5)释放GPU内存 CUDA内存管理API (1)分配内存 cudaErro

Java - BigDecimal 计算分位(百分位)

日常开发中,如果使用数据库来直接查询一组数据的分位数,就比较简单,直接使用对应的函数就可以了,例如:         PERCENT_RANK() OVER(PARTITION BY 分组列名 ORDER BY 目标列名) AS 目标列名_分位数         如果是需要在代码逻辑部分进行分位数的计算,就需要我们自己写一个工具类来支持计算了 import static ja

OpenStack离线Train版安装系列—2计算节点-环境准备

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

新一代车载(E/E)架构下的中央计算载体---HPC软件架构简介

老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节能减排。 无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事.而不是让内心的烦躁、焦虑、毁掉你本就不多的热情和定力。 时间不知不觉中,快要来到夏末秋初。一年又过去了一大半,成