// Arup Guha
// 10/22/2021
// Fast Modular Exponentiation

#include <stdio.h>
#include <time.h>

long long slowModExpo(long long base, long long exp, long long mod);
long long fastModExpo(long long base, long long exp, long long mod);

// Test code
int main(void) {

    // Run slow code.
    int s1 = time(0);
    long long ans1 = slowModExpo(12345678, 10000000000LL, 1000000007);
    int e1 = time(0);
    printf("answer is %lld\n", ans1);
    printf("took %d seconds.\n", e1-s1);

    // And fast code
    int s2 = time(0);
    long long ans2 = fastModExpo(12345678, 10000000000LL, 1000000007);
    int e2 = time(0);
    printf("answer is %lld\n", ans2);
    printf("took %d seconds.\n", e2-s2);

    return 0;
}

// Regular modular exponentiation
long long slowModExpo(long long base, long long exp, long long mod) {

    // Silly base case.
    if (mod == 1) return 0;

    // Just multiply in base exp # of times.
    long long ans = 1;
    for (long long i=0; i<exp; i++)
        ans = (ans*base)%mod;

    // Return the answer!
    return ans;
}

// Fast modular exponentiation.
long long fastModExpo(long long base, long long exp, long long mod) {

    // Base cases...
    if (mod == 1) return 0;
    if (exp == 0) return 1;

    // Here is where we save time!!!
    if (exp%2 == 0) {
        long long tmp = fastModExpo(base,exp/2,mod);
        return (tmp*tmp)%mod;
    }

    // Regular break down.
    return base*fastModExpo(base,exp-1,mod)%mod;
}
