• MillerRabin素性测试


    如题,这个主要是对于大整数(比如200位的十进制数),而且能够以很高的概率得到正确的判断

    比如下面这个程序判断10000以内的素数,正确率达到98.95%

    因为素性测试目前貌似没有有效的确定性算法(所谓有效,应该是指判断n是否为素数,花费时间T是n的位数的多项式),所以这个概率算法很有用

    用概率算法是不是始终不放心?虽然错误概率很小,毕竟还是存在啊。实际上,当算法的错误概率小于机器的硬件出错的概率时,这就不是问题了(是的,硬件也会出错的,而且你的程序运行时间越长,出错概率越大)

    关于这个算法,算法导论上也有讲,可以到那里了解算法的原理(偷个懒- -)

    //MillerRabin素性测试,概率算法
    //n is an odd number larger than 4, n - 1 = 2^s * t
    //t is an odd number
    //a is a member of B(n) iff 2 <= a <= n - 2 and satisfy either of the two
    //conditions below:
    //1) a^t ≡ 1 mod n
    //2) for all i ∈ [0,s) and i is an integer, a^(2^i*t) = -1 mod n
    //Btest return true if a is a member of B(n)
    #include <stdio.h>
    #include <time.h>
    #include <math.h>
    #include <stdlib.h>
    bool Btest(int a, int n)//n is odd, a is a member of [2, n - 2]
    {
        int s = 0, t = n - 1;
        while (t % 2 == 0) {
            t /= 2; s++;
        }
        int x = 1;
        for (int i = 0; i < t; i++) {
            x = x * a % n;
        }
        if (x == 1 || x == n - 1) {
            return true;
        }
        for (int i = 0; i < s; i++) {
            x = x * x % n;
            if (x == n - 1) {
                return true;
            }
        }
        return false;
    }
    bool MillRab(int n){
        srand((unsigned)time(NULL));
        int a = rand() % (n - 3) + 2;
        return Btest(a,n);
    }
    bool RepeatMillRab(int n, int k)//repeat k times
    {
        for (int i = 0; i < k; i++) {
            if (MillRab(n) == false) {
                return false;
            }
        }
        return true;
    }
    bool isPrime(int n){
        int bound = sqrt(n);
        for (int i = 2; i <= bound; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
    void printPrimes(){
        printf("2, 3, ");
        for (int n = 5; n < 10000; n += 2) {
            if (RepeatMillRab(n, floor(log(n) / log(2)))) {
                printf("%d, ", n);
            }
        }
        printf("\n");
    }
    void deterministicPrintPrime(){
        printf("2, 3, ");
        for (int n = 5; n < 10000; n += 2) {
            if (isPrime(n)) {
                printf("%d, ", n);
            }
        }
    }
    int main(int argc, const char *argv[])
    {
        deterministicPrintPrime();
        printf("time used: %.4lf s\n", (double)clock() / CLOCKS_PER_SEC);
        return 0;
    }
  • 相关阅读:
    【洛谷6776】[NOI2020] 超现实树(思维)
    【洛谷6773】[NOI2020] 命运(线段树合并优化DP)
    【洛谷5467】[PKUSC2018] PKUSC(计算几何)
    【洛谷3688】[ZJOI2017] 树状数组(二维线段树)
    【BZOJ4543】[POI2014] Hotel加强版(长链剖分优化DP)
    【洛谷5466】[PKUSC2018] 神仙的游戏(FFT)
    【BZOJ4574】[ZJOI2016] 线段树(动态规划)
    【洛谷7114】[NOIP2020] 字符串匹配(Z函数)
    扩展 KMP(Z 函数)学习笔记
    最后的胡言乱语
  • 原文地址:https://www.cnblogs.com/fstang/p/2849807.html
Copyright © 2020-2023  润新知