1175-质数排列

Raphael Liu Lv10

请你帮忙给从 1n 的数设计排列方案,使得所有的「质数」都应该被放在「质数索引」(索引从 1 开始)上;你需要返回可能的方案总数。

让我们一起来回顾一下「质数」:质数一定是大于 1 的,并且不能用两个小于它的正整数的乘积来表示。

由于答案可能会很大,所以请你返回答案 模 mod 10^9 + 7 之后的结果即可。

示例 1:

**输入:** n = 5
**输出:** 12
**解释:** 举个例子,[1,2,5,4,3] 是一个有效的排列,但 [5,2,3,4,1] 不是,因为在第二种情况里质数 5 被错误地放在索引为 1 的位置上。

示例 2:

**输入:** n = 100
**输出:** 682289015

提示:

  • 1 <= n <= 100

方法一:质数判断 + 组合数学

思路

求符合条件的方案数,使得所有质数都放在质数索引上,所有合数放在合数索引上,质数放置和合数放置是相互独立的,总的方案数即为「所有质数都放在质数索引上的方案数」\times「所有合数都放在合数索引上的方案数」。求「所有质数都放在质数索引上的方案数」,即求质数个数 numPrimes 的阶乘。「所有合数都放在合数索引上的方案数」同理。求质数个数时,可以使用试除法。「204.计数质数的官方题解 」列举了更多的求质数个数方法,读者可以根据兴趣阅读。最后注意计算过程中需要对 10^9+7 取模。

代码

[sol1-Python3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution:
def numPrimeArrangements(self, n: int) -> int:
numPrimes = sum(self.isPrime(i) for i in range(1, n + 1))
return self.factorial(numPrimes) * self.factorial(n - numPrimes) % (10 ** 9 + 7)

def isPrime(self, n: int) -> int:
if n == 1:
return 0
for i in range(2, int(sqrt(n)) + 1):
if n % i == 0:
return 0
return 1

def factorial(self, n: int) -> int:
res = 1
for i in range(1, n + 1):
res *= i
res %= (10 ** 9 + 7)
return res
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
static final int MOD = 1000000007;

public int numPrimeArrangements(int n) {
int numPrimes = 0;
for (int i = 1; i <= n; i++) {
if (isPrime(i)) {
numPrimes++;
}
}
return (int) (factorial(numPrimes) * factorial(n - numPrimes) % MOD);
}

public boolean isPrime(int n) {
if (n == 1) {
return false;
}
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}

public long factorial(int n) {
long res = 1;
for (int i = 1; i <= n; i++) {
res *= i;
res %= MOD;
}
return res;
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Solution {
const int MOD = 1000000007;

public int NumPrimeArrangements(int n) {
int numPrimes = 0;
for (int i = 1; i <= n; i++) {
if (IsPrime(i)) {
numPrimes++;
}
}
return (int) (Factorial(numPrimes) * Factorial(n - numPrimes) % MOD);
}

public bool IsPrime(int n) {
if (n == 1) {
return false;
}
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}

public long Factorial(int n) {
long res = 1;
for (int i = 1; i <= n; i++) {
res *= i;
res %= MOD;
}
return res;
}
}
[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const int MOD = 1e9 + 7;

class Solution {
public:
int numPrimeArrangements(int n) {
int numPrimes = 0;
for (int i = 1; i <= n; i++) {
if (isPrime(i)) {
numPrimes++;
}
}
return (int) (factorial(numPrimes) * factorial(n - numPrimes) % MOD);
}

bool isPrime(int n) {
if (n == 1) {
return false;
}
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}

long factorial(int n) {
long res = 1;
for (int i = 1; i <= n; i++) {
res *= i;
res %= MOD;
}
return res;
}
};
[sol1-C]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define MOD 1000000007

bool isPrime(int n) {
if (n == 1) {
return false;
}
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}

long factorial(int n) {
long res = 1;
for (int i = 1; i <= n; i++) {
res *= i;
res %= MOD;
}
return res;
}

int numPrimeArrangements(int n){
int numPrimes = 0;
for (int i = 1; i <= n; i++) {
if (isPrime(i)) {
numPrimes++;
}
}
return (int) (factorial(numPrimes) * factorial(n - numPrimes) % MOD);
}
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const mod int = 1e9 + 7

func numPrimeArrangements(n int) int {
numPrimes := 0
for i := 2; i <= n; i++ {
if isPrime(i) {
numPrimes++
}
}
return factorial(numPrimes) * factorial(n-numPrimes) % mod
}

func isPrime(n int) bool {
for i := 2; i*i <= n; i++ {
if n%i == 0 {
return false
}
}
return true
}

func factorial(n int) int {
f := 1
for i := 1; i <= n; i++ {
f = f * i % mod
}
return f
}
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const MOD = 1000000007;
var numPrimeArrangements = function(n) {
let numPrimes = 0;
for (let i = 2 ; i <= n ; i++) {
if (isPrime(i)) {
numPrimes++;
}
}
let res = 1;
let m = n - numPrimes;
while (numPrimes > 0) {
res = res % MOD;
res *= numPrimes;
numPrimes--;
}
while (m > 0) {
res = res % MOD;
res *= m;
m--;
}
return res;
};

const isPrime = (n) => {
if (n === 1) {
return false;
}
for (let i = 2; i * i <= n; i++) {
if (n % i === 0) {
return false;
}
}
return true;
}

复杂度分析

  • 时间复杂度:O(n^{3/2})。求 n 个数中质数个数的时间复杂度为 O(n^{3/2}),阶乘的时间复杂度为 O(n),总的时间复杂度为 O(n^{3/2})。

  • 空间复杂度:O(1),只使用了常数空间。

 Comments
On this page
1175-质数排列