爱拉托斯散算法
【C++代码实现】
#include<iostream>
#include<math.h>
using namespace std;
int main() {
long long int n;
cout << "请输入一个正整数N:\n";
cin >> n;
cout << "不超过N的素数有:\n";
long long int* number = new long long int[n + 1];
bool* del = new bool[n + 1];
for (int i = 2; i <= n; i++) {
number[i] = i;
del[i] = false;// 初始化数组,false表示为素数未被删除
}
// 删除算法
for (int i = 2; i <= sqrt(n); i++) {
if (del[i] == false) {
for (int j = number[i] * 2; j <= n; j += number[i]) {
del[j] = true; // 如果此时number[i]为素数,则开始删除其倍数,若不是素数则不会进入该循环
}
}
}
int flag = 1;
// 打印输出小于N的素数,每一行输出十个数字
for (int i = 2; i <= n; i++) {
if (del[i] == false) {
if (flag++ != 10)
cout << number[i] << "\t";
else {
flag = 1;
cout << number[i] << endl;
}
}
}
return 0;
}
【编译结果】
满足爱拉托斯散算法删除结果
两位大整数的和与积
【C++代码实现】
#include<iostream>
#include<vector>
using namespace std;
int main()
{
string s1, s2;
vector<int> num1; // 输入的大整数1
vector<int> num2; // 输入的大整数2
vector<int> num_add;// 大整数求和结果
vector<int> num_mul;// 大整数求积结果
cout << "请输入两个小于100位的大整数:\n";
cin >> s1 >> s2;
int len1 = s1.length();
int len2 = s2.length();
int len_max, len_min, flag = 0;
if (len1 > len2) {
len_max = len1;
len_min = len2;
flag = 1;
}
else {
len_max = len2;
len_min = len1;
}
for (int i = len1 - 1; i >= 0; i--) {
int a = s1[i] - 48;
num1.push_back(a);
}
for (int i = len2 - 1; i >= 0; i--) {
int a = s2[i] - 48;
num2.push_back(a);
}
int d = 0, a = 0;
//加法操作
for (int i = 0; i < len_max; i++) {
if (i < len_min) {
a = num1[i] + num2[i] + d;
if (a >= 10) {
d = 1;
a = a - 10;
}
else
d = 0;
num_add.push_back(a);
}
else {
if (flag == 1) {
a = num1[i] + d;
if (a >= 10) {
d = 1;
a = a - 10;
}
else
d = 0;
num_add.push_back(a);
}
else {
a = num2[i] + d;
if (a >= 10) {
d = 1;
a = a - 10;
}
else
d = 0;
num_add.push_back(a);
d = 0;
}
}
}
if (d == 1) num_add.push_back(d);
cout << "两位大整数和为:\n";
for (int i = num_add.size() - 1; i >= 0; i--) {
cout << num_add[i];
}
//乘法操作
d = 0;
for (int i = 0; i < len1; i++) {
if (d != 0) {
num_mul.push_back(d);
d = 0;
}
for (int j = 0; j < len2; j++) {
int k = i + j;
a = num1[i] * num2[j] + d;
if (a >= 10) {
d = a / 10;
a = a % 10;
}
else
d = 0;
if (k >= num_mul.size())
num_mul.push_back(a);
else
num_mul[k] += a;
}
}
if (d != 0) num_mul.push_back(d);
for (int i = 0; i < num_mul.size(); i++) {
if (num_mul[i] >= 10) {
num_mul[i + 1] += num_mul[i] / 10;
num_mul[i] = num_mul[i] % 10;
}
}
cout << "\n两位大整数积为:\n";
for (int i = num_mul.size() - 1; i >= 0; i--) {
cout << num_mul[i];
}
return 0;
}
【编译结果】
满足两位大整数的和与积结果
模P二次剩余(欧拉判别法)
【实验原理】
【C++代码实现】
#include<iostream>
using namespace std;
int main()
{
cout << "请输入一个不为0的整数a和一个奇素数p:\n";
int a, p;
cin >> a >> p;
int n = (p - 1) / 2, tmp = 1;
for (int i = 0; i < n; i++)
{
tmp = (tmp * a) % p;
}
if (tmp == 1) cout << a << " 是模 " << p << " 的平方剩余。\n";
if (tmp == p - 1) cout << a << " 是模 " << p << " 的平方非剩余。\n";
return 0;
}
【编译结果】
结果正确。
Fermat素性检测和爱拉托散筛法素性检测
【实验原理】
Fermat素性检测:
爱拉托散筛法:
【C++代码实现】
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <math.h>
using namespace std;
int gcd(int x, int y) {
int t;
// 广义欧几里得除法
while (y) {
t = x;
x = y;
y = t % y;
}
return x;
}
int p; // 待检测的奇数
// Fermat素性检测
int Fermat() {
int flag = 1; // p为素数判断标志
// 对rand函数进行初始化
unsigned seed;
seed = time(0);
srand(seed);
// 进行10次判断,正确概率为 1023/1024
for (int i = 0; i < 10; i++) {
int n = p;
// 随机抽取b(0<b<n)
int b = rand() % (n - 1) + 1;
// 利用广义欧几里得除法算得b和p的最大公因数
int d = gcd(b, n);
if (d > 1) {
flag = 0;
break;
}
else {
long long int r = 1;
while (n != 1) {
r = (r * b) % p;
n--;
}
if (r != 1) {
flag = 0;
break;
}
}
}
return flag;
}
// 爱拉托散筛法素性检测
int al() {
int flag = 0, n = p+1; // flag为素数判断标志
int* number = new int[n + 1];
bool* del = new bool[n + 1];
for (int i = 2; i <= n; i++) {
number[i] = i;
del[i] = false;// 初始化数组,false表示为素数未被删除
}
// 删除算法
for (int i = 2; i <= sqrt(n); i++) {
if (del[i] == false) {
for (int j = number[i] * 2; j <= n; j += number[i]) {
del[j] = true; // 如果此时number[i]为素数,则开始删除其倍数,若不是素数则不会进入该循环
}
}
}
for (int i = 2; i <= n; i++) {
if (del[i] == false && number[i] == p) {
flag = 1;
break;
}
}
return flag;
}
int main()
{
cout << "请输入一个奇数p:\n";
cin >> p;
cout << "Fermat素性检测结果:\n";
if (Fermat() == 1) cout << p << "是一个素数!\n";
else cout << p << "不是一个素数!\n";
cout << "爱拉托散筛法素性检测结果:\n";
if (al() == 1) cout << p << "是一个素数!\n";
else cout << p << "不是一个素数!\n";
return 0;
}
【编译结果】
【效率分析】
对于Fermat素性检测,为概率检测,利用循环进行了10次判断,正确概率为 1023/1024。时间复杂度主要由计算r=b^n-1 (mod p)时产生,利用while循环,时间复杂度为O(n),又由于进行了10次判断,故时间复杂度为O(10n)。只用了几个变量存储中间数据,空间复杂度为O(c)。
对于爱拉托散筛法素性检测,为确定性检测。时间复杂度主要由删除算法产生,利用了循环内再套用循环,故时间复杂度为O(n^2)。用了两组长度为n+1的数组来记录数据及是否删除,空间复杂度为O(2n)。
经过比较,我们发现,Fermat素性检测虽然为概率检测,但时间复杂度远低于爱拉托散筛法素性检测,对于比较大的奇数,也是Fermat素性检测更占优势。