计算以素数为模的逆表

时间:2012-12-24 00:52:19

标签: algorithm primes

我知道扩展的欧几里德算法是计算单个模数 p 的乘法逆的理想方法。

但是,如果我想创建一个数组 A A [x] 与x的倒数有什么影响呢?有没有更快的方法来计算这样的数组然后通过单独计算每个元素的倒数?

我直觉地期望有一条捷径,因为你有很多身份,比如

A[x*y % p] = A[x]*A[y] % p

但是,我无法想到获得整个数组 A 的一般方法。

3 个答案:

答案 0 :(得分:3)

将反转计算减半的简单方法是使用

inverse(p - k) = p - inverse(k)

并使用扩展的欧几里德算法仅填充数组的前半部分,剩余的一半使用对称性。

我不确定以下内容是否更快,计算量更少,但对阵列的访问模式更差,因此可能会更慢:

int A[p] = {0};
A[1] = 1;
for(int k = 2; k < p; ++k) {
    if (A[k] == 0) {
        // haven't found the inverse yet
        inv = inverse(k,p); // extended Euclidean algorithm or Fermat's theorem
        int m = k, i = inv;
        while(m != 1) {
            A[m] = i;
            m = (m*k) % p;
            i = (i*inv) % p;
        }
    }
}

每次遇到一个你还不知道的逆的值时,你会迭代计算每个元素只使用两个模乘(除了初始求逆)之前由该值生成的整个子群的逆。您应该相对很快地命中模块p的整个单元组的生成器。

答案 1 :(得分:2)

对于p素数,元素{1,2,3,...,(p-1)}形成一个循环群。也就是说,存在多个(实际上很多)x使得{x ^ 0,x ^ 1,x ^ 2,...,x ^(p-2)}是该集合。在找到x的倒数后,将其称为y,您可以通过简单地将y提升到适当的幂来得到相应的求逆,y ^ k是x ^ k的倒数。你怎么找到这样的x?选择一个随机元素并将其提升到(p-1)/ 2的幂。该数字将为1或-1(p-1)。如果它是-1,你有你的发电机。将元素提升为幂应该使用“通过平方取幂”来完成。

答案 2 :(得分:0)

以下代码是从mod函数的定义派生的:

enter image description here

public long[] InverseTable(long n, long p)
{
    long[] inverse = new long[n+1];
    inverse[1] = 1;
    for (long i = 2; i <= n; i++)
        inverse[i] = p - (inverse[p % i] * (p / i) % p);
    return inverse;
}