-2

I'm trying to calculate, for 0 < n ≤ 10⁹, the value of

re=(2^n)%1000000007

I wrote this code:

int main()
{
    int n,i,re=1;
    scanf("%d",&n);
    for(i=0; n>i; i++) re=(2*re)%1000000007;
    printf("%d",re);
}

When n is 10⁹, my code takes too long.

What can I do to make it faster?

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Mostafa
  • 1
  • 4
  • 1
    [Code Review](https://codereview.stackexchange.com/) – Arun A S Dec 14 '17 at 16:00
  • 1
    @ArunAS Only if a decent description of the problem is given and the code in question is actually written by the OP. Take a look at [their help-center](https://codereview.stackexchange.com/help/on-topic). – Mast Dec 14 '17 at 16:02
  • @Mast yes, but I'm sure that the OP can access the full question since he is using an online judge. But your suggestion is indeed useful. When migrating to code review, there should be working code and good description – Arun A S Dec 14 '17 at 16:05
  • You can remove the `%1000000007` for the first 30 iterations. – mch Dec 14 '17 at 16:05
  • @ArunAS Exactly. Migrate this as-is and the wrath of the community will descend on both the question and SO. – Mast Dec 14 '17 at 16:11
  • The best way to eliminate the error is to use a more efficient algorithm. HTH. – Toby Speight Dec 14 '17 at 16:57
  • Hint: what's `2^2`? `2^4`? `2^8`,`2^16`,`2^32`, ...? And you know that `2^(4+1)` == `2^4 * 2^1`, so you can generalize that. No need to iterate a billion times. – Toby Speight Dec 14 '17 at 17:01

3 Answers3

1

You can follow binary exponentiation which will be something like

#define MOD 1000000007

long long fastExp(int b, int e) {
    long long r=1;
    while(e>0) {
       if(e&1) r=(r*b)%MOD;
       b=(b*b)%MOD;
       e/=2;
    }
    return r%MOD;
}

Call it like this fastExp(2,n).

Well the complexity is pretty simple in that it does log2(n) operations so this will work better than your O(n) solution.

As an explanation to why your solution got TLE. The online judges available like that of SPOJ etc usually take 1 sec to do 10^8 loop operations. Here you do much more than that when you have n=10^9 as input.

user2736738
  • 30,591
  • 5
  • 42
  • 56
0

You can do it in logarithmic time of n by computing power computation faster.

#include <stdio.h>
#include <stdint.h>

const int kMod = 1000000007;

int Pow(int b, int p) {
    if (p == 0) return 1;
    int x = Pow(b, p >> 1);
    return ((((int64_t)x * x) % kMod) * (p & 1? b : 1)) % kMod;
}

int main()
{
    int n;
    scanf("%d", &n);
    //for(i=0; n>i; i++) re=(2*re)%1000000007;
    int re = Pow(2, n);
    printf("%d\n", re);
    return 0;
}

For example, 25 means computation of x = 22 and x * x * 2.

abdullah
  • 662
  • 5
  • 7
0

If n is smaller than 30, the result is 1 << n, otherwise you can calculate 1 << 30 and let your for loop start at 31. You can also get rid of the expensive % operation if you check if (re > 1000000007) and subtract 1000000007 (because re is smaller than 1000000007 before multiplying it by 2, it is smaller than 2*1000000007, so subtracting 1000000007 is enough):

int foo(int n)
{
    if (n < 30) return 1 << n;
    int re = (1 << 30) % 1000000007;
    for(int i=31; n>i; i++)
    {
        re <<= 1;
        if (re > 1000000007) re -= 1000000007;
    }
    return re;
}

complete program: https://ideone.com/0FRcaf

mch
  • 9,424
  • 2
  • 28
  • 42