算法 – 从(n ^ j)计算(n 1)^ j的最快方法

我需要计算一些非常大的k和j(均为几百万的数量级)的0 ^ j,1 ^ j,…,k ^ j.我正在使用GMP来处理大整数(是的,我需要整数,因为我需要全精度).现在,我想,一旦我完成了计算n ^ j的努力,是不是有办法加速(n 1)^ j的计算,而不是从头开始?

以下是我目前用于计算功率的算法:

mpz_class pow(unsigned long int b, unsigned long int e)
{
    mpz_class res = 1;
    mpz_class m = b;

    while(e)
    {
        if(e & 1)
        {
            res *= m;   
        }

        e >>= 1;
        m *= m;
    }

    return res;
}

正如您所看到的,每次我从头开始,都需要花费很多时间.

最佳答案 为了计算n ^ j,为什么不找到至少一个n因子,比如k执行n ^ j = k ^ j *(n / k)^ j?到计算n ^ j时,k ^ j和(n / k)^ j都应该是已知的.

但是,上面的n可能是O(sqrt(n))时间.正如您在上面的代码中所提到的,我们在O(log(j))时间内独立计算了n ^ j(Exponentiation by Squaring).

所以你可以混合使用上面哪个更大:

>如果n远小于log(j),则通过分解计算n ^ j.
>每当知道n ^ j时,计算{(2 * n)^ j,(3 * n)^ j,…,((n-1)* n)^ j,n * n ^ j}并保留它在查找表中.
>如果n大于log(j)且无法进行如上所述的就绪计算,请使用对数方法,然后计算上述其他相关功率.
>如果n是2的纯幂(可能是const time computation),则通过移位计算第j个幂并计算相关的和.
>如果n为偶数(再次计算常数时间),请使用分解方法并计算相关产品.

以上应该会很快.例如,偶数的识别本身应该将一半的功率计算转换为乘法.可能会有更多关于因子分解的拇指规则可以进一步减少计算(特别是对于3,7等的可分性)

点赞