Count Good Numbers

medium math recursion fast power

Problem

A length-n digit string is good when every digit at an even index (0-indexed) is even (one of 0,2,4,6,8 → 5 choices) and every digit at an odd index is prime (one of 2,3,5,7 → 4 choices). Count all good strings of length n modulo 109+7. Since n can reach 1015, the count is 5⌈n/2⌉ · 4⌊n/2⌋ computed with fast exponentiation.

Inputn = 4
Output400
Indices 0 and 2 are even (5 choices each), indices 1 and 3 are odd (4 choices each): 5 · 4 · 5 · 4 = 400.

def countGoodNumbers(n):
    MOD = 10**9 + 7

    def power(base, exp):           # fast modular exponentiation
        base %= MOD
        result = 1
        while exp > 0:
            if exp & 1:             # current bit set: fold base in
                result = result * base % MOD
            base = base * base % MOD # square the base
            exp >>= 1               # drop the lowest bit
        return result

    even_slots = (n + 1) // 2       # indices 0,2,4,... -> 5 choices
    odd_slots = n // 2              # indices 1,3,5,... -> 4 choices
    return power(5, even_slots) * power(4, odd_slots) % MOD
function countGoodNumbers(n) {
  const MOD = 1000000007n;

  function power(base, exp) {        // fast modular exponentiation
    base %= MOD;
    let result = 1n;
    while (exp > 0n) {
      if (exp & 1n)                  // current bit set: fold base in
        result = result * base % MOD;
      base = base * base % MOD;       // square the base
      exp >>= 1n;                    // drop the lowest bit
    }
    return result;
  }

  const evenSlots = (n + 1n) / 2n;   // indices 0,2,4,... -> 5 choices
  const oddSlots = n / 2n;           // indices 1,3,5,... -> 4 choices
  return Number(power(5n, evenSlots) * power(4n, oddSlots) % MOD);
}
int countGoodNumbers(long n) {
    long MOD = 1_000_000_007L;

    long evenSlots = (n + 1) / 2;    // indices 0,2,4,... -> 5 choices
    long oddSlots = n / 2;           // indices 1,3,5,... -> 4 choices
    return (int) (power(5, evenSlots, MOD) * power(4, oddSlots, MOD) % MOD);
}

long power(long base, long exp, long MOD) {  // fast modular exponentiation
    base %= MOD;
    long result = 1;
    while (exp > 0) {
        if ((exp & 1) == 1)          // current bit set: fold base in
            result = result * base % MOD;
        base = base * base % MOD;     // square the base
        exp >>= 1;                   // drop the lowest bit
    }
    return result;
}
long long power(long long base, long long exp, long long MOD) {
    base %= MOD;
    long long result = 1;
    while (exp > 0) {
        if (exp & 1)                 // current bit set: fold base in
            result = result * base % MOD;
        base = base * base % MOD;     // square the base
        exp >>= 1;                   // drop the lowest bit
    }
    return result;
}

int countGoodNumbers(long long n) {
    long long MOD = 1e9 + 7;
    long long evenSlots = (n + 1) / 2;   // indices 0,2,... -> 5 choices
    long long oddSlots = n / 2;          // indices 1,3,... -> 4 choices
    return (int)(power(5, evenSlots, MOD) * power(4, oddSlots, MOD) % MOD);
}
Time: O(log n) Space: O(1)