素数判定法——MR素性测试

素数判定法——MR素性测试

/ 0评 / 1874次 / 2

这是一个随机性算法,有可能会被卡!!!

素数是数论中地位突出的一个环节,对于素数的判断同样是研究不断,在我之前的博文中已经简单的说过了欧拉筛,这是一种确定性算法,可以保证得到的结果是准确的,并且在多组数据的判断中很占优势,但其本身的空间复杂度仍是难以处理的一点

而MR素性测试则是很好的处理了这一点,在针对离散型数据的素数判断中在时间与空间上有很大的优势,因为其本身是是从结论的角度去进行的验证性算法。

先说理论,本质是小费马定理的逆运用

  1. /*
  2. * @Author: Gehrychiang
  3. * @LastEditors : Please set LastEditors
  4. * @Website: www.yilantingfeng.site
  5. * @E-mail: gehrychiang@aliyun.com
  6. */
  7. #include <bits/stdc++.h>
  8. using namespace std;
  9. long long fastMul(long long a, long long b, long long mod) //a*b % mod
  10. {
  11. long long res = 0;
  12. while (b)
  13. {
  14. if (b & 1)
  15. {
  16. res = (res + a) % mod;
  17. }
  18. a = (a + a) % mod;
  19. b >>= 1;
  20. }
  21. return res;
  22. }
  23. long long fastPowMod(long long a, long long n, long long mod) //a^n % mod
  24. {
  25. if (n == 0 && a != 0)
  26. return 1;
  27. if (n != 0 && a == 0)
  28. return 0;
  29. long long base = a;
  30. long long res = 1;
  31. while (n)
  32. {
  33. if (n & 1)
  34. {
  35. res = fastMul(res, base, mod);
  36. }
  37. base = fastMul(base, base, mod);
  38. n >>= 1;
  39. }
  40. return res % mod;
  41. }
  42. bool mr_test(long long n, long long a, long long d)
  43. {
  44. if (n == 2) //n是2
  45. return true;
  46. if (n % 2 == 0) //n为偶数
  47. return false;
  48. if (n == a) //二者相等了,其实这种情况并不会出现,已经在组测试中得到了True的返回值
  49. return false;
  50. // 存在某个i使得a^(d*2^i) mod n=n-1 i>=0
  51. while (!d & 1) //确保d为奇数
  52. {
  53. d >>= 1; // d/=2
  54. }
  55. long long t = fastPowMod(a, d, n);
  56. while (d != n - 1 && t != n - 1 && t != 1)
  57. {
  58. t = fastMul(t, t, n);
  59. d <<= 1; // d*=2 这里用来还原前面的取成奇数的过程也就是把d朝n-1复原的过程
  60. }
  61. return t == n - 1 || t == 1; //如果最后我们的可以等于n-1或是为1那么就是通过了这一组测试
  62. }
  63. bool mr_test_grp(long long n)
  64. {
  65. if (n == 1)
  66. return false;
  67. int a[10] = {2, 3, 5, 7, 11, 13, 17, 19, 47, 61};
  68. for (int i = 0; i < 10; i++)
  69. {
  70. if (n == a[i])
  71. return true;
  72. if (!mr_test(n, a[i], n - 1)) //有一组没通过素性测试
  73. return false;
  74. }
  75. //更多的随机数样本测试,一般来说,工业级代码需要要求通过1k组以上的测试才能保证判断的准确性
  76. // srand(5201314);
  77. // for (int i = 0; i < 33; i++)
  78. // {
  79. // long long r=rand()%(n-1)+1;
  80. // if(n==r)
  81. // return true;
  82. // if(!mr_test(n,r,n-1))
  83. // return false;
  84. // }
  85. return true; //全部通过 此时大概率是素数
  86. }
  87. int main()
  88. {
  89. long long n;
  90. cin >> n;
  91. if (mr_test_grp(n))
  92. {
  93. cout << "yes" << endl;
  94. }
  95. else
  96. {
  97. cout << "no" << endl;
  98. }
  99. return 0;
  100. }
/*
 * @Author: Gehrychiang
 * @LastEditors  : Please set LastEditors
 * @Website: www.yilantingfeng.site
 * @E-mail: gehrychiang@aliyun.com
 */
#include <bits/stdc++.h>
using namespace std;

long long fastMul(long long a, long long b, long long mod) //a*b % mod
{
    long long res = 0;
    while (b)
    {
        if (b & 1)
        {
            res = (res + a) % mod;
        }
        a = (a + a) % mod;
        b >>= 1;
    }
    return res;
}

long long fastPowMod(long long a, long long n, long long mod) //a^n % mod
{
    if (n == 0 && a != 0)
        return 1;
    if (n != 0 && a == 0)
        return 0;
    long long base = a;
    long long res = 1;
    while (n)
    {
        if (n & 1)
        {
            res = fastMul(res, base, mod);
        }
        base = fastMul(base, base, mod);
        n >>= 1;
    }
    return res % mod;
}

bool mr_test(long long n, long long a, long long d)
{
    if (n == 2) //n是2
        return true;
    if (n % 2 == 0) //n为偶数
        return false;
    if (n == a) //二者相等了,其实这种情况并不会出现,已经在组测试中得到了True的返回值
        return false;
    //  存在某个i使得a^(d*2^i) mod n=n-1  i>=0
    while (!d & 1) //确保d为奇数
    {
        d >>= 1; // d/=2
    }
    long long t = fastPowMod(a, d, n);
    while (d != n - 1 && t != n - 1 && t != 1)
    {
        t = fastMul(t, t, n);
        d <<= 1; // d*=2  这里用来还原前面的取成奇数的过程也就是把d朝n-1复原的过程
    }
    return t == n - 1 || t == 1; //如果最后我们的可以等于n-1或是为1那么就是通过了这一组测试
}

bool mr_test_grp(long long n)
{
    if (n == 1)
        return false;
    int a[10] = {2, 3, 5, 7, 11, 13, 17, 19, 47, 61};
    for (int i = 0; i < 10; i++)
    {
        if (n == a[i])
            return true;
        if (!mr_test(n, a[i], n - 1)) //有一组没通过素性测试
            return false;
    }
    //更多的随机数样本测试,一般来说,工业级代码需要要求通过1k组以上的测试才能保证判断的准确性
    // srand(5201314);
    // for (int i = 0; i < 33; i++)
    // {
    //     long long r=rand()%(n-1)+1;
    //     if(n==r)
    //     return true;
    //     if(!mr_test(n,r,n-1))
    //     return false;
    // }

    return true; //全部通过  此时大概率是素数
}
int main()
{
    long long n;
    cin >> n;
    if (mr_test_grp(n))
    {
        cout << "yes" << endl;
    }
    else
    {
        cout << "no" << endl;
    }

    return 0;
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

你好 No.96910