#include "RandomNumber.h"
#include <iostream>
#include <cstdlib>
using namespace std;
/**
* 计算 a^p mod n
* @param a 底数
* @param p 指数
* @param n 模数
* @param result 保存结果
* @param composite 标识是否为合数
*/
void power(unsigned int a, unsigned int p, unsigned int n, unsigned int &result, bool &composite) {
result = 1;
unsigned int base = a % n;
while (p > 0) {
if (p % 2 == 1) {
result = (result * base) % n;
}
base = (base * base) % n;
p /= 2;
}
composite = (result != 1);
}
/**
* 判断一个数是否为素数,使用 Miller-Rabin 素性测试
* @param n 待判断的数
* @return true 如果是素数,否则返回 false
*/
bool Prime(unsigned int n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
unsigned int s = 0;
unsigned int d = n - 1;
while (d % 2 == 0) {
d /= 2;
s++;
}
// 使用 a = 2, 3 来进行初步测试
unsigned int a[2] = {2, 3};
for (int i = 0; i < 2; i++) {
unsigned int x;
bool composite;
power(a[i], d, n, x, composite);
if (x == 1 || x == n - 1) continue;
bool witness = false;
for (unsigned int j = 0; j < s - 1; j++) {
power(x, 2, n, x, composite);
if (x == n - 1) {
witness = true;
break;
}
}
if (!witness) return false;
}
return true;
}
/**
* Miller-Rabin 素性测试,进行 k 次测试
* @param n 待判断的数
* @param k 测试次数
* @return true 如果可能是素数,否则返回 false
*/
bool PrimeMC(unsigned int n, unsigned int k) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0) return false;
unsigned int s = 0;
unsigned int d = n - 1;
while (d % 2 == 0) {
d /= 2;
s++;
}
for (unsigned int i = 0; i < k; i++) {
unsigned int a = 2 + rand() % (n - 3); // 选择随机的 a
unsigned int x;
bool composite;
power(a, d, n, x, composite);
if (x == 1 || x == n - 1) continue;
bool witness = false;
for (unsigned int j = 0; j < s - 1; j++) {
power(x, 2, n, x, composite);
if (x == n - 1) {
witness = true;
break;
}
}
if (!witness) return false;
}
return true;
}
int main() {
unsigned int n;
cin >> n;
if (PrimeMC(n, 5)) { // 使用5次测试
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
return 0;
}
-
power
函数:- 计算
a^p mod n
,并判断结果是否为合数。 - 使用快速幂算法来高效计算幂。
- 计算
-
Prime
函数:- 使用 Miller-Rabin 素性测试初步判断数
n
是否为素数。 - 初步测试中使用底数
2
和3
进行快速判断。
- 使用 Miller-Rabin 素性测试初步判断数
-
PrimeMC
函数:- 使用 Miller-Rabin 素性测试进行
k
次随机测试,判断数n
是否为素数。 - 随机选择一个底数
a
进行测试,重复k
次。
- 使用 Miller-Rabin 素性测试进行
-
主函数:
- 从标准输入读取正整数
n
。 - 调用
PrimeMC
函数进行素性测试,并根据结果输出 "Yes" 或 "No"。
- 从标准输入读取正整数