zoukankan      html  css  js  c++  java
  • 网络安全课 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
    ", (t2 - t1) * 1.0 / 1000);
        return 0;
    }
    

      

      

      

  • 相关阅读:
    day29
    day28
    day27
    查询区间内有多少个不同的数(线段树/树状数组)
    树状数组变形:带区间修改的树状数组
    特征提取:PCA主成分分析法和NMF非负矩阵分解法
    Trie树
    Logistic&Softmax回归
    高斯贝叶斯分类器(GNB实战)
    朴素贝叶斯分类器(伯努利贝叶斯+高斯贝叶斯+多项式贝叶斯)
  • 原文地址:https://www.cnblogs.com/Stephen-Jixing/p/12736077.html
Copyright © 2011-2022 走看看