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.
 
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

 
Constraints:

1 <= n <= 100

Difficulty: EASY
Starter code: class Solution:
    def numPrimeArrangements(self, n: int) -> int:
        

Solutions:
class Solution:

	def numPrimeArrangements(self, n: int) -> int:
		primes = [True] * (n + 1)
		for prime in range(2, int(math.sqrt(n)) + 1):
			if primes[prime]:
				for composite in range(prime * prime, n + 1, prime):
					primes[composite] = False
		cnt = sum(primes[2:])
		return math.factorial(cnt) * math.factorial(n - cnt) % (10 ** 9 + 7)


class Solution:

	def numPrimeArrangements(self, n: int) -> int:
		primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101]
		for i in range(len(primes)):
			if primes[i] > n:
				break
		count = i
		print(count)
		return math.factorial(count) % (10 ** 9 + 7) * math.factorial(n - count) % (10 ** 9 + 7)


class Solution:

	def numPrimeArrangements(self, n: int) -> int:
		p_nums = []
		c_nums = []
		dp = [True for _ in range(n + 1)]
		dp[0] = False
		dp[1] = False
		for i in range(2, n + 1):
			if dp[i] == True:
				cnt = 2
				while i * cnt < n + 1:
					dp[i * cnt] = False
					cnt += 1
		for i in range(1, n + 1):
			if dp[i]:
				p_nums += [i]
			else:
				c_nums += [i]
		return self.fact(len(p_nums) % (10 ** 9 + 7)) * self.fact(len(c_nums)) % (10 ** 9 + 7)

	def fact(self, n):
		if n <= 1:
			return 1
		else:
			return n * self.fact(n - 1)


class Solution:

	def numPrimeArrangements(self, n: int) -> int:

		def fac(m):
			result = 1
			for i in range(1, m + 1):
				result *= i
			return result

		def PrimeTell(m):
			if m == 1 or m == 4:
				return False
			if m == 2 or m == 3:
				return True
			for j in range(2, m // 2):
				if m % j == 0:
					return False
			return True
		Sum = 0
		for i in range(1, n + 1):
			if PrimeTell(i):
				Sum += 1
		return fac(Sum) * fac(n - Sum) % (10 ** 9 + 7)


class Solution:

	def numPrimeArrangements(self, n: int) -> int:
		if n == 1:
			return 1
		p = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
		if n < 98:
			(lo, hi) = (0, 24)
			while lo <= hi:
				mid = (hi - lo) // 2 + lo
				if p[mid] == n:
					idx = mid + 1
					break
				elif p[mid - 1] < n and n < p[mid]:
					idx = mid
					break
				elif p[mid] > n:
					hi = mid - 1
				else:
					lo = mid + 1
		else:
			idx = 25
		p_prod = 1
		for i in range(1, idx + 1):
			p_prod = p_prod * (i % 1000000007) % 1000000007
		c_prod = 1
		for i in range(1, n - idx + 1):
			c_prod = c_prod * (i % 1000000007) % 1000000007
		return p_prod * c_prod % 1000000007


class Solution:

	def numPrimeArrangements(self, n: int) -> int:
		primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
		r = sum((1 for p in primes if p <= n))
		a = 10 ** 9 + 7
		ans = 1
		for i in range(1, min(r, n - r) + 1):
			ans *= (i % a) ** 2
			ans %= a
		for i in range(min(r, n - r) + 1, max(r, n - r) + 1):
			ans *= i
			ans %= a
		return ans