网络安全课 06 【Euler、Fermat定理、Miller-Rabin 概率算法】
计算最大公因数、最小公倍数



Euler 函数



Fermat定理

星期四的计算需要由中间过程,推算出3^3000%6 = 3 而 3^3%7 = 6
大数的素数分解

Miller-Rabin大数 素性检测实现
视频讲解链接(需要梯子)
https://www.youtube.com/watch?v=eC6YCv6sMzE
C++实现代码:
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <time.h>
#include <Windows.h>
using namespace std;
#ifndef ll
#define ll long long
#endif
// rand 2 - e
ll rand_Number(ll e) {
return rand() % e + 1;
}
// a*b % c 快速乘 + mod
ll mult_mod(ll a, ll b, ll c) {
a %= c;
b %= c;
ll res = 0;
while (b) {
if (b & 1) {
res += a;
res %= c;
}
a <<= 1; //左移一位 相当于 a*=a
if (a >= c) a %= c;
b >>= 1; //b 下一位
}
return res;
}
//a^u % num 快速幂 里面套快速乘
ll getRemainder(ll a, ll u, ll num) {
ll cur = 1;
ll nxt = a;
while (u) {
if (u & 1) {
cur = mult_mod(cur, nxt, num); //cur *=nxt %num
}
nxt = mult_mod(nxt, nxt, num); //nxt *=nxt
u = u >> 1;
}
return cur % num;
}
bool checkPrime(ll num) {
int S = 20; //检测次数
if (num == 2) {
return true;
}
if (num < 2 || num % 2 == 0) {
return false;
}
ll u = num - 1; //肯定是偶数
while (u % 2 == 0) {
u /= 2;
}
//这个时候 num = 2^(u*k) + 1
for (int i = 0; i < S; i++) {
ll a = rand_Number(num - 1); //随机取一个小于num的数做检测 作为底数a^u % num
ll x = getRemainder(a, u, num); //a^u % num
ll x_1;
ll tu = u;
while (tu < num) {
x_1 = mult_mod(x, x, num); //x=a^u x*x=a^2u x*x % num
if (x_1 == 1 && x != 1 && x != num - 1) {
//如果x_1==1 要满足 上一个x 是 1 or num-1 才没有非平凡根
//如果出现根不是 1 or num-1 那么就存在非平凡根 那num就是和数
return false;
}
if (x_1 == 1 && (x == 1 || x == num - 1)) {
//已经出现1 后面再平方没意义
return true;
}
x = x_1;
tu *= 2; //继续平方 算 a^2u a^4u a^8u
}
if (x != 1) {
return false;
}
}
return true;
}
int main() {
ll n;
scanf("%lld", &n);
DWORD t1, t2;
t1 = GetTickCount();
if (checkPrime(n)) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
t2 = GetTickCount();
printf("Use Time:%f\n", (t2 - t1) * 1.0 / 1000);
return 0;
}

浙公网安备 33010602011771号