我想在等式x ^ 3 + 1 = 0 mod p中求解x。 p是素数。我使用https://eprint.iacr.org/2009/457.pdf
上的论文实现了我的代码我得到正确答案p%3 == 2,但p%2 = 1的错误答案。有人可以帮助我吗?
import java.io.*;
import java.util.*;
import java.math.*;
class cube_root {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long a = sc.nextInt();
long p = sc.nextInt();
long x = f(a, p);
System.out.println(x);
}
public static long f(long a, long p) {
if (p == 2) {
return 1;
}
if (p == 3) {
return 2;
}
long q = GCD(3, p - 1);
long x = powmod(a, (p - 1) / q, p);
if (x != 1) {
return -1;
}
long m = p - 1;
long s = 0;
for (; m % 3 == 0; m /= 3) {
s++;
}
long t = m;
long k = m / 3;
long rem = m % 3;
long b = 0;
for (long i = 2; i < p; i++) {
long g = GCD(3, p - 1);
long y = powmod(i, (p - 1) / g, p);
if (y != 1) {
b = i;
break;
}
}
long c = powmod(b, t, p);
long r = powmod(a, t, p);
long h = 1L;
long cp = powmod(c, (long)Math.pow(3, (int)s - 1), p);
c = inv(c, p);
for (long i = 1; i < s; i++) {
long d = powmod(r, (long)Math.pow(3, (int)(s - t - 1)), p);
if (d == cp) {
h *= c;
r *= (c * c * c);
} else if (d != 1 || d == cp * cp) {
h *= (c * c);
r *= ((c * c * c) * (c * c * c));
}
c = powmod(c, 3, p);
}
r = h * powmod(a, k, p);
if (rem == 1) {
r = inv(r, p);
}
return r;
}
public static long GCD(long a, long b) {
if (b == 0) {
return a;
}
return GCD(b, a % b);
}
public static long powmod(long a, long p, long n) {
long r = a % n;
if (p == 0) {
return 1;
}
if (p == 1) {
return r;
}
if (p % 2 == 1) {
r = powmod(a, p / 2, n) % n;
r = r * r % n;
return r * a % n;
} else {
r = powmod(a, p / 2, n) % n;
r = r * r % n;
return r;
}
}
public static long inv(long a, long p) {
return powmod(a, p - 2, p);
}
}
答案 0 :(得分:0)
在该论文中没有太多研究算法的情况下,我建议您调试程序并查找这些错误:
(选择代码片段只是为了说明错误,您需要仔细检查程序实际执行的操作以及应该执行的操作)
<强> 1。溢出错误
e.g。
long r = powmod(a, t, p);
...
r *= ((c * c * c) * (c * c * c));
long
对于你在这里做的事情可能不够大。
长的范围大约是2 ^ 64,并且它的cuberoot大约是2642245.在这种情况下长时间溢出并不困难。
考虑使用BigInteger。
<强> 2。一个错误
e.g。
for (; m % 3 == 0; m /= 3) {
s++;
}
s
会增加吗?再一次?少一点时间?