【问题标题】:What is the best algorithm to determine if N is a prime number (if N is [2 <= N <= 2^63-1])?确定 N 是否为素数(如果 N 为 [2 <= N <= 2^63-1])的最佳算法是什么?
【发布时间】:2020-09-25 14:18:07
【问题描述】:

我尝试使用 Miller-Rabin 算法,但它无法检测到非常大的数字。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

long long mulmod(long long a, long long b, long long mod)
{
    long long x = 0,y = a % mod;
    while (b > 0)
    {
        if (b % 2 == 1)
        {    
            x = (x + y) % mod;
        }
        y = (y * 2) % mod;
        b /= 2;
    }
    return x % mod;
}

long long modulo(long long base, long long exponent, long long mod)
{
    long long x = 1;
    long long y = base;
    while (exponent > 0)
    {
        if (exponent % 2 == 1)
        {
            x = (x * y) % mod;  
        }
        y = (y * y) % mod;
        exponent = exponent / 2;
    }
    return x % mod;
}

int Miller(unsigned long long int p, int iteration)
{
    int i;
    long long s;
    if (p < 2)
    {
        return 0;
    }
    if (p != 2 && p % 2==0)
    {
        return 0;
    }
    s = p - 1;
    while (s % 2 == 0)
    {
        s /= 2;
    }
    for (i = 0; i < iteration; i++)
    {
        long long a = rand() % (p - 1) + 1, temp = s;
        long long mod = modulo(a, temp, p);
        while (temp != p - 1 && mod != 1 && mod != p - 1)
        {
            mod = mulmod(mod, mod, p);
            temp *= 2;
        }
        if (mod != p - 1 && temp % 2 == 0)
        {
            return 0;
        }
    }
    return 1;
}

int main()
{
    int iteration = 5, cases;
    unsigned long long int num;
    scanf("%d", &cases);
    for(int i = 0; i < cases; i++)
    {
        scanf("%llu", &num);
        if(Miller(num, iteration))
        {
            printf("YES\n");    
        } 
        else
        {
            printf("NO\n");
        }   
    }
    return 0;
}

输出示例:

10 //cases
1
NO
2
YES
3
YES
4
NO
5
YES
1299827
YES
1951
YES
379
YES
3380
NO
12102
NO

我正在尝试通过创建一个程序来判断数字是否为素数,如果素数则打印 YES,否则打印 NO。但是,每次我将代码提交给在线评委时,它只会显示“错误答案”,而即使我最后一次尝试做作业也没有任何有效的算法,它会显示“超出时间限制”。

当N为[2

【问题讨论】:

  • 请提供此类输入的示例
  • return x % mod; 可以写成return x;,因为x 总是更新% mod(也许编译器对其进行了优化……但为什么要相信编译器呢?)。
  • 你得到最大可能的质数 P 小于 2^63 并且对于给定的 N 计算 N^(P-1) mod P 并查看它是否为 1。
  • 在 Linux Debian 上,您可以找到几个开源素数生成器(例如 primesieve-bin 包)。另请阅读primality test 上的维基页面。阅读 Modern C 和您的 C 编译器(例如 GCC...)和调试器(例如 GDB...)的文档
  • 米勒-拉宾的重点是将非常个大素数从复合物中分离出来;小于 64 位的数字根本不是“非常大”。如果您正确实施,Miller-Rabin 绝对可以工作。

标签: c primality-test


【解决方案1】:

OP 的代码有许多溢出 63 位数学的可能性。例如x * y in x = (x * y) % mod;

至少,建议去 unsigned 数学。例如:long long --> unsigned long long 或简单的uintmax_t

对于不会溢出的mulmod()Modular exponentiation without range restriction


稍后我会对此进行更多研究。 GTG。

【讨论】:

    猜你喜欢
    • 2011-11-16
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 2013-05-15
    相关资源
    最近更新 更多