计算和存储非常大的数字的功率

时间:2015-05-18 06:46:42

标签: c++ algorithm modular-arithmetic

我发现pow(2,i)可以在i范围内0<=i<=100000. i    除powers[100000]; powers[0]=1; for (i = 1; i <=100000; ++i) { powers[i]=(powers[i-1]*2)%MOD; } 之外,MOD = 1000000007

i=100000

对于i=70,功率值不会大于MOD吗?

如何正确存放电量?

这个操作对我来说看起来不太可行。 我估计值正确到{{1}}最大值。

我必须找到sum + = ar [i] * power(2,i),最后打印总和%1000000007,其中ar [i]是一个附加数组,其中一些大数字高达10 ^ 5

2 个答案:

答案 0 :(得分:2)

只要您的模数值小于数据类型容量的一半,就不会超过它。这是因为你取了0..1000000006范围内的先前值,加倍它,然后重新模数它将它带回到相同的范围。

但是,我不能保证更高的价值不会给你带来麻烦,它比我准备投资的数学分析更为简单。您可以花费大量时间进行分析,检查和调试,但最好不要让问题首先发生。

另类?我倾向于使用预生成方法(让程序预先进行gruntwork,将预先生成的值轻松地插入到数组中,并且可以从真正的程序中快速访问)。 / p>

使用此方法,您可以使用经过良好测试和已知的工具来处理大量值。由于这些数据不会改变,因此每次程序启动时都无法计算数据。

如果您希望以简单(高效)的方式执行此操作,则以下bash脚本与bcawk一起执行此操作:

#!/usr/bin/bash

bc >nums.txt <<EOF
    i = 1;
    for (x = 0;x <= 10000; x++) {
        i % 1000000007;
        i = i * 2;
    }
EOF

awk 'BEGIN { printf "static int array[] = {" }
           { if (NR % 5 == 1) printf "\n    ";
             printf "%s, ",$0;
             next
           }
     END   { print "\n};" }' nums.txt

bc部分是&#34;肉&#34;这件事,它创造​​了两个大的力量,并以你提供的数量为模输出它们。 awk部分只是用C风格的数组元素格式化它们,每行五个。

只需获取它的输出并将其放入您的代码中,瞧,你有它,一个编译时耗费的数组,你可以用来快速查找。

我的盒子只需要一秒半的时间来生成阵列,然后永远不会再次需要这样做。你也不必担心模数学的变幻莫测: - )

static int array[] = {
    1,2,4,8,16,
    32,64,128,256,512,
    1024,2048,4096,8192,16384,
    32768,65536,131072,262144,524288,
    1048576,2097152,4194304,8388608,16777216,
    33554432,67108864,134217728,268435456,536870912,
    73741817,147483634,294967268,589934536,179869065,
    359738130,719476260,438952513,877905026,755810045,
    511620083,23240159,46480318,92960636,185921272,
    371842544,743685088,487370169,974740338,949480669,
    898961331,797922655,595845303,191690599,383381198,
    766762396,533524785,67049563,134099126,268198252,
    536396504,72793001,145586002,291172004,582344008,
    164688009,329376018,658752036,317504065,635008130,
    270016253,540032506,80065005,160130010,320260020,
    640520040,281040073,562080146,124160285,248320570,
    :
    861508356,723016705,446033403,892066806,784133605,
    568267203,136534399,273068798,546137596,92275185,
    184550370,369100740,738201480,476402953,952805906,
    905611805,
};

答案 1 :(得分:0)

如果您注意到您的模数可以存储在int中。 MOD = 1000000007(十进制)相当于0b00111011100110101100101000000111,可以32位存储。

 - i      pow(2,i)        bit representation 
 - 0            1         0b00000000000000000000000000000001
 - 1            2         0b00000000000000000000000000000010 
 - 2            4         0b00000000000000000000000000000100 
 - 3            8         0b00000000000000000000000000001000
 - ...
 - 29   536870912         0b00100000000000000000000000000000

当pow(2,i)比你的MOD = 1000000007更大时,棘手的部分开始,但如果你知道当前的pow(2,i)将大于你的MOD,你可以实际看到MOD之后的位是怎样的

 - i      pow(2,i)  pow(2,i)%MOD      bit representation
 - 30   1073741824  73741817    0b000100011001010011000000000000
 - 31   2147483648  147483634   0b001000110010100110000000000000
 - 32   4294967296  294967268   0b010001100101001100000000000000
 - 33   8589934592  589934536   0b100011001010011000000000000000

所以如果你有pow(2,i-1)%MOD,你可以在pow(2,i-1)%MOD上做* 2直到你下一次战斗(2,i)将大于MOD

在i = 34的示例中,您将使用(589934536 * 2)MOD 1000000007而不是(8589934592 * 2)MOD 1000000007,因为8589934592无法存储在int中。

另外,您可以尝试位操作而不是乘以pow(2,i)。 与乘法2相同的位操作是位shift left