Prime Arrangements
EasyUpdated: Aug 2, 2025
Practice on:
Problem
Return the number of permutations of 1 to n so that prime numbers are at prime indices (1-indexed.)
(Recall that an integer is prime if and only if it is greater than 1, and cannot be written as a product of two positive integers both smaller than it.)
Since the answer may be large, return the answer modulo 10^9 + 7.
Examples
Example 1:
Input:
n = 5
Output:
12
Explanation: For example [1,2,5,4,3] is a valid permutation, but [5,2,3,4,1] is not because the prime number 5 is at index 1.
Example 2:
Input:
n = 100
Output:
682289015
Solution
Method 1 – Prime Counting and Factorial Product
Intuition
The key idea is that the only way to satisfy the condition is to place all primes at prime indices and all non-primes at non-prime indices. The number of ways to arrange the primes among the prime indices is the factorial of the number of primes, and similarly for non-primes.
Approach
- Count the number of primes up to
n(let's call itp). - The number of non-primes is
n - p. - The answer is
p! * (n-p)!modulo10^9 + 7. - Use the Sieve of Eratosthenes to efficiently count primes.
- Compute factorials modulo
10^9 + 7.
Code
C++
class Solution {
public:
int numPrimeArrangements(int n) {
int mod = 1e9 + 7;
vector<bool> isPrime(n+1, true);
isPrime[0] = isPrime[1] = false;
for (int i = 2; i * i <= n; ++i) {
if (isPrime[i]) {
for (int j = i * i; j <= n; j += i) isPrime[j] = false;
}
}
int p = 0;
for (int i = 2; i <= n; ++i) if (isPrime[i]) ++p;
long long ans = 1;
for (int i = 2; i <= p; ++i) ans = (ans * i) % mod;
for (int i = 2; i <= n - p; ++i) ans = (ans * i) % mod;
return ans;
}
};
Go
func numPrimeArrangements(n int) int {
mod := int(1e9 + 7)
isPrime := make([]bool, n+1)
for i := 2; i <= n; i++ { isPrime[i] = true }
for i := 2; i*i <= n; i++ {
if isPrime[i] {
for j := i * i; j <= n; j += i {
isPrime[j] = false
}
}
}
p := 0
for i := 2; i <= n; i++ {
if isPrime[i] { p++ }
}
ans := 1
for i := 2; i <= p; i++ { ans = ans * i % mod }
for i := 2; i <= n-p; i++ { ans = ans * i % mod }
return ans
}
Java
class Solution {
public int numPrimeArrangements(int n) {
int mod = 1000000007;
boolean[] isPrime = new boolean[n+1];
Arrays.fill(isPrime, true);
isPrime[0] = isPrime[1] = false;
for (int i = 2; i * i <= n; i++) {
if (isPrime[i]) {
for (int j = i * i; j <= n; j += i) isPrime[j] = false;
}
}
int p = 0;
for (int i = 2; i <= n; i++) if (isPrime[i]) p++;
long ans = 1;
for (int i = 2; i <= p; i++) ans = ans * i % mod;
for (int i = 2; i <= n - p; i++) ans = ans * i % mod;
return (int)ans;
}
}
Kotlin
class Solution {
fun numPrimeArrangements(n: Int): Int {
val mod = 1_000_000_007
val isPrime = BooleanArray(n+1) { true }
isPrime[0] = false; isPrime[1] = false
for (i in 2..n) {
if (isPrime[i]) {
var j = i * i
while (j <= n) {
isPrime[j] = false
j += i
}
}
}
var p = 0
for (i in 2..n) if (isPrime[i]) p++
var ans = 1L
for (i in 2..p) ans = ans * i % mod
for (i in 2..(n-p)) ans = ans * i % mod
return ans.toInt()
}
}
Python
class Solution:
def numPrimeArrangements(self, n: int) -> int:
mod = 10**9 + 7
is_prime = [True] * (n+1)
is_prime[0] = is_prime[1] = False
for i in range(2, int(n**0.5)+1):
if is_prime[i]:
for j in range(i*i, n+1, i):
is_prime[j] = False
p = sum(is_prime)
ans = 1
for i in range(2, p+1):
ans = ans * i % mod
for i in range(2, n-p+1):
ans = ans * i % mod
return ans
Rust
impl Solution {
pub fn num_prime_arrangements(n: i32) -> i32 {
let n = n as usize;
let mut is_prime = vec![true; n+1];
is_prime[0] = false;
is_prime[1] = false;
for i in 2..=((n as f64).sqrt() as usize) {
if is_prime[i] {
let mut j = i * i;
while j <= n {
is_prime[j] = false;
j += i;
}
}
}
let p = is_prime.iter().filter(|&&x| x).count();
let mut ans: i64 = 1;
let m = 1_000_000_007;
for i in 2..=p { ans = ans * i as i64 % m; }
for i in 2..=(n-p) { ans = ans * i as i64 % m; }
ans as i32
}
}
TypeScript
class Solution {
numPrimeArrangements(n: number): number {
const mod = 1e9 + 7;
const isPrime = Array(n+1).fill(true);
isPrime[0] = isPrime[1] = false;
for (let i = 2; i * i <= n; i++) {
if (isPrime[i]) {
for (let j = i * i; j <= n; j += i) isPrime[j] = false;
}
}
let p = 0;
for (let i = 2; i <= n; i++) if (isPrime[i]) p++;
let ans = 1;
for (let i = 2; i <= p; i++) ans = ans * i % mod;
for (let i = 2; i <= n - p; i++) ans = ans * i % mod;
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(n log log n)for the sieve, andO(n)for factorials, so overallO(n). - 🧺 Space complexity:
O(n)for the sieve array.