立方残基模数素数

时间:2014-12-02 15:05:08

标签: java algorithm

我想在等式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);
    }
}

1 个答案:

答案 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会增加吗?再一次?少一点时间?