【发布时间】: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