Focus on 2 n mod p first, because you can always subtract it at the end.
Consider the powers of two. This is a sequence of numbers created by multiplying by two.
Consider the operation modulo. If the number is written in the base p, you just grab the last digit. Higher numbers may be discarded.
So, at some point in the sequence, you get a two-digit number (1 in a p-place), and your task is to simply get rid of the first digit (subtract p) when this happens.
Staying here conceptually, the brute force approach would be something like this:
uint64_t exp2modp( uint64_t n, uint64_t p ) { uint64_t ret = 1; uint64_t limit = p / 2; n %= p; // Apply Fermat Little Theorem. while ( n -- ) { if ( ret >= limit ) { ret *= 2; ret -= p; } else { ret *= 2; } } return ret; }
Unfortunately, this still lasts forever for large n and p, and I cannot come up with any theory of higher numbers.
If you have a multiplication tool that can calculate (p-1) ^ 2 without overflow, then you can use a similar algorithm, using repeated squaring with the module after each square operation, and then take the product of a series of squares leftovers, again with the module after each multiplication.
source share