すべての「素数」が「素数インデックス」(インデックスは 1 から始まります)に配置されるように、1 から n までの数値の配置を設計するのを手伝ってください。可能な解の総数を返す必要があります。
一緒に「素数」について復習しましょう。素数は 1 より大きくなければならず、それより小さい 2 つの正の整数の積で表すことはできません。
答えは非常に大きい可能性があるため、答えを 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
アイデア
- 素数の位置は入れ替えることができ、非素数と非素数の位置も入れ替えることができます。
- x 個の素数がある場合、x! 種類の順列が存在し、y 個の非素数がある場合、y! 種類の順列が存在し、x!*y! 種類の順列が存在します。
- 知らせ
- 各計算ステップでは、係数を取得する必要があります。
- 中間変数を定義するには、long long を使用します。
- 最終的に返された結果の剰余を取ることを忘れないでください。
#include "bits/stdc++.h"
using namespace std;
int MOD = 1e9 + 7;
int MAXN = 100;
class Solution {
public:
void getPrime() {
isPrime.resize(MAXN + 1, true);
isPrime[0] = isPrime[1] = false;
for (int i = 2; i <= MAXN; ++i) {
if (isPrime[i]) {
for (int j = 2 * i; j <= MAXN; j += i) {
isPrime[j] = false;
}
}
}
}
int numPrimeArrangements(int n) {
if (n == 1) {
return 1;
}
getPrime();
// 质数之间位置可以互换,非质数和非质数之间也可以互换
// 若质数有x个,则有x!种排列;非质数有y个,则有y!中排列;则共有x!*y!种排列
long long x = 0;
for (int i = 1; i <= n; ++i) {
if (isPrime[i]) {
++x;
}
}
long long y = n - x;
for (int i = x - 1; i >= 2; --i) {
x = (x * i) % MOD;
}
for (int i = y - 1; i >= 2; --i) {
y = (y * i) % MOD;
}
return (x * y) % MOD;
}
private:
vector<bool> isPrime;
};
- 素数ふるい法 ふるい
法を使用して素数を見つける基本的な考え方:
A (A>=2) が素数の場合、A の N (N>=2) 倍は素数であってはなりません。
C
++ コード:
// 初始化为true
vector<int> isPrime(range + 1, true);
// 0和1都不是素数
isPrime[0] = isPrime[1] = false;
// 从2开始,将非素数设置为false
for (int i = 2; i <= range; ++i) {
if (isPrime[i]) {
for (int j = 2 * i; j <= range; j += i) {
isPrime[j] = false;
}
}
}
最適化: