计算和打印(2 ^ N-1)mod(10 ^ 9 + 7),用于C中的大N.

时间:2013-11-10 21:58:25

标签: c math

我遇到一个问题,我给出了一个名为N的T号列表(T是输入的第一行),我必须为每个号码打印((2^N)-1)%(10^9+7)。以下限制适用:

1 ≤ T ≤ 100
1 ≤ N ≤ 100000000

我得到的是低整数的正确答案,但不适用于高整数。我认为这与math.h中的pow()函数有关,但我不确定。

这是我的代码:

#include <stdio.h>
#include <math.h>

int main(void) {
    unsigned int t, i;
    long long unsigned int ans, n, m = 1000000007;
    scanf("%u", &t);
    for (i = 0; i < t; ++i) {
        scanf("%llu", &n);
        ans = ((long long unsigned int)pow(2,n)-1)%m;
        printf("%llu\n", ans);
    }
    return 0;
}

所以基本上当我给我的程序这个输入时:

6
1
2
3
4
5
100000000

我得到了输出:

1
3
7
15
31
582344007

我的输出的前5行是正确的,但我想得到最后一行494499947。

See here for the wolfram alpha output which gives the correct answer.

对不起,如果我的问题很简单,我还在学习C的详细信息。

3 个答案:

答案 0 :(得分:4)

pow(2, 100000000)的结果超过3000万位数。它无法转换为整数类型(即使long long unsigned int) - 它太大了!

您需要使用modular exponentiation来获得准确的结果。

答案 1 :(得分:1)

您的方法非常耗时,大小超过2 ^ 64(很长很长)。 正如你的问题中所说,你想要找到2 ^ 100000000。精确地 O(n)需要“100000000”这么多次迭代。 因此更好的方法是使用模幂运算。 它不仅在 O(log n)时间计算,而且在中间步骤使用mod 10 ^ 9 + 7给出整数(long long)范围的答案。

   mod=10^9+7;


 powermod(x,y)
         res:=1
             while(y>0)
                 if y&1
                    res=res*x%mod

                x=x*x%mod
                y=y>>1
         return res

答案 2 :(得分:0)

你正在调用pow,这需要一倍。如果你想要最大范围,至少在Linux上使用powl,这需要很长的时间。 您的程序缺少检查溢出,范围错误等。如果(似乎)您对结果的正确性感兴趣,那么您应该添加这些。 我想你只需要更仔细地阅读'man pow': - )