Skip to content
← All posts

Prime Arrangements: Counting Permutations of Primes and Composites

5 min read
leetcodeproblemeasymath

Return the number of permutations of 1 to n so that prime numbers are at prime indices (1-indexed), modulo 10^9 + 7.

This is LeetCode 1175: Prime Arrangements. A few examples:

  • n = 5 returns 12 (3 primes at 3 prime indices, 2 non-primes at 2 non-prime indices: 3! * 2! = 12)
  • n = 100 returns 682289015
  • n = 1 returns 1 (no primes, only one arrangement)

The constraint is 1 <= n <= 100, so the solution does not need to handle enormous inputs. But the modular arithmetic still matters because factorials grow fast.

Positions 1 through 512345pos 1pos 2pos 3pos 4pos 5Primes (3 values)Non-primes (2 values)235143! = 6 arrangements2! = 2 arrangementsTotal: 3! x 2! = 6 x 2 = 12prime positionnon-prime position
For n = 5, positions 2, 3, 5 are prime and positions 1, 4 are non-prime. Primes must land on prime positions and non-primes on non-prime positions. Each group can be arranged in factorial-many ways.

The approach

Think about what the problem is really asking. You have positions 1 through n, and you need to place numbers 1 through n into those positions. The rule: every prime number must land on a prime-indexed position, and every non-prime number must land on a non-prime-indexed position.

Since primes and non-primes occupy completely separate slots, the two groups are independent. You can arrange the primes among prime positions in any order, and separately arrange the non-primes among non-prime positions in any order. The total count is just the product of the two groups' arrangement counts.

How many ways can you arrange k items into k slots? That is k! (k factorial). So the answer is:

factorial(primeCount) * factorial(n - primeCount) mod (10^9 + 7)

The entire problem reduces to one subproblem: count how many primes exist in the range [1, n]. Once you have that, a couple of factorial computations finish the job.

For n up to 100, you can check primality by trial division. For larger ranges, a sieve would be faster, but trial division is perfectly fine here.

Counting primes up to n

A number k is prime if it is greater than 1 and has no divisors other than 1 and itself. For small k, you can check this by testing divisors from 2 up to the square root of k. If none divide evenly, the number is prime.

This is the same logic from the Sieve of Eratosthenes, but since n is at most 100, a simple loop works fine.

Python solution

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

    def is_prime(k):
        if k < 2:
            return False
        for d in range(2, int(k**0.5) + 1):
            if k % d == 0:
                return False
        return True

    prime_count = sum(1 for i in range(1, n + 1) if is_prime(i))
    non_prime_count = n - prime_count

    result = 1
    for i in range(1, prime_count + 1):
        result = result * i % MOD
    for i in range(1, non_prime_count + 1):
        result = result * i % MOD

    return result

Walkthrough

Let's trace through numPrimeArrangements(10) step by step.

Tracing numPrimeArrangements(10):

Step 1: Count primes up to 10

12345678910
primes: 2, 3, 5, 7|count = 4

Use a sieve or trial division: check each number from 2 to 10.

Step 2: Count non-primes

non-prime count: 10 - 4 = 6

Non-primes are 1, 4, 6, 8, 9, 10. That is n - primeCount = 10 - 4 = 6.

Step 3: Compute factorial(4) for prime positions

4! = 4 * 3 * 2 * 1 = 24

The 4 primes can occupy the 4 prime-indexed positions in any order.

Step 4: Compute factorial(6) for non-prime positions

6! = 6 * 5 * 4 * 3 * 2 * 1 = 720

The 6 non-primes fill the 6 non-prime-indexed positions in any order.

Step 5: Multiply and take modulo

24 * 720 = 17280
17280 mod (10^9 + 7) = 17280

The two groups are independent, so total arrangements = 4! * 6! mod (10^9 + 7).

Result: numPrimeArrangements(10) = 17280

Count primes up to n, then multiply factorial(primeCount) by factorial(n - primeCount). The modular arithmetic only matters for larger values of n where the product exceeds 10^9 + 7.

The key observation is that we never build any permutations. We just count primes, compute two factorials, and multiply. The combinatorics do all the heavy lifting.

Complexity analysis

ApproachTimeSpace
Generate all permutations and filterO(n! * n)O(n)
Count primes + multiply factorialsO(n * sqrt(n))O(1)

The prime-counting loop runs n iterations. Each primality check takes O(sqrt(n)) in the worst case. The factorial computations are O(n) combined. No extra data structures are needed beyond a few variables.

For n up to 100, both approaches finish instantly, but the factorial approach scales gracefully while brute force does not.

The building blocks

This problem is built on two reusable patterns:

Prime counting. You need to identify which numbers in a range are prime. Whether you use trial division or a sieve depends on the range size. For n up to 100, trial division is the right call. For n up to 10^6 or beyond, the Sieve of Eratosthenes becomes essential. Recognizing when you need a prime count is the first step in many number theory problems.

Factorial as a counting tool. The number of ways to arrange k distinct items into k distinct slots is k!. This is the fundamental counting principle in action: the first slot has k choices, the second has k - 1, and so on. Whenever a problem asks "how many permutations satisfy some constraint," check whether the constraint splits items into independent groups. If it does, the answer is a product of factorials.

Edge cases to watch for

Before submitting, make sure your solution handles these:

  • n = 1: The only number is 1, which is not prime. There are 0 primes and 1 non-prime. 0! * 1! = 1 * 1 = 1.
  • n = 2: Primes: . Non-primes: . 1! * 1! = 1.
  • n = 3: Primes: . Non-primes: . 2! * 1! = 2.
  • n = 100: The answer is 682289015. Make sure you apply the modulo at each multiplication step, not just at the end, to avoid integer overflow in languages with fixed-width integers.
  • 1 is not prime: This trips people up. 1 has only one divisor (itself), so it fails the "exactly two distinct divisors" definition of a prime.

From understanding to recall

You have seen that the problem boils down to counting primes and multiplying factorials. The logic is clean: split positions into prime and non-prime, count each group, compute factorials, multiply.

But knowing the approach and producing it under pressure are different things. The connection you need to internalize is: "independent groups of items filling independent groups of slots" maps to "product of factorials." That pattern appears in many counting problems, and the only way to make it automatic is repeated practice.

Spaced repetition helps here. Solve this problem from scratch today, then revisit it in a few days. Each time, you rebuild the prime-counting step and the factorial multiplication from memory. After a few rounds, the pattern is second nature.

Related posts

  • Count Primes - The classic prime-counting problem using the Sieve of Eratosthenes, which gives you the primeCount this problem needs
  • Factorial Trailing Zeroes - Another problem where reasoning about factorial properties avoids computing the factorial itself
  • Combinations - A backtracking problem where counting arrangements (C(n, k)) is the core idea, connecting to the factorial-based counting used here