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

时间:2017-01-28 09:44:48

标签: algorithm pow

对于一些非常大的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;
}

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

2 个答案:

答案 0 :(得分:1)

您可能希望使用(n + 1)^ j的二项式展开为n ^ j + j n ^(j-1)+ j (j-1)/ 2 * n ^(j-2)+ ... + 1并且记忆已经计算的较低功率并且通过加法重新使用它们来在O(n)时间内计算(n + 1)^ j。如果在添加每个项时逐步计算系数j,j *(j-1)/ 2,...,也可以在O(n)中完成。

答案 1 :(得分:1)

要计算n^j,为什么不找到n的至少一个因素,比如k执行n^j = k^j * (n/k)^j?在计算n^j时,k^j(n/k)^j都应该是已知的。

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

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

  1. 如果log(j)远小于n^j,请按分解计算n^j

  2. 每当{(2*n)^j, (3*n)^j, ..., ((n-1)*n)^j, n * n^j}知道计算n并将其保存在查找表中时。

  3. 如果log(j)大于n并且无法进行如上所述的就绪计算,请使用对数方法,然后计算上述其他相关功能。

  4. 如果2j的纯粹力量(可能为Exponentiation by Squaring),请通过移位计算n幂并计算相关总和。

  5. 如果import Vue from 'vue' import Zoom from 'src/components/Zoom' import $ from 'jquery' /* eslint-disable no-unused-vars */ /** * get template for wrapper Vue object make Vue with Zoom component and that template * @param wrapperTemplate * @returns {Vue$2} */ const makeWrapper = (wrapperTemplate = '<div><zoom ref="component"></zoom></div>') => { return new Vue({ template: wrapperTemplate, components: {Zoom} }) } const startWrapperWidth = 1093 const startWrapperHeight = 289 const startImageWidth = 1696 const startImageHeight = 949 const padding = 15 /** * gets vueWrapper and return component from it * @param vueWrapper * @param useOffset * @returns {'Zoom component'} */ const setSizesForComponent = (vueWrapper) => { vueWrapper.$mount() var cmp = vueWrapper.$refs.component var $elWrapper = $(cmp.$el) var $elImage = $elWrapper.find(cmp.selectors.image) $elWrapper.width(startWrapperWidth) $elWrapper.height(startWrapperHeight) $elWrapper.css({padding: padding}) $elImage.width(startImageWidth) $elImage.height(startImageHeight) cmp.calculateSizesAndProportions() return cmp } describe('onZoom method (run on mousemove)', () => { sinon.spy(Zoom.methods, 'onZoom') let vueWrapper = makeWrapper() let cmp = setSizesForComponent(vueWrapper) let e = document.createEvent('HTMLEvents') e.initEvent('mousemove', true, true) e.pageX = 150 e.pageY = 250 let callsOnZoomBeforeMousemove = Zoom.methods.onZoom.callCount cmp.$el.dispatchEvent(e) describe('left and top computed props', () => { it('left', () => { expect(cmp.left).is.equal(-74) }) it('top', () => { expect(cmp.top).is.equal(-536) }) }) }) 是偶数(再次计算常数时间),请使用分解方法并计算相关产品。

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