题解:P12237 [蓝桥杯 2023 国 Java A] 质数排序
整体思路
为表述方便,记:质数下标元素集合为
由于
一、C 内部的逆序对
共有
二、C 与 P 之间的逆序对
考虑非质数下标位置
考虑
因此位置
将每个位置
代码实现
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int mod = 998244353;
struct Euler{
vector<int>primes;
vector<bool>comp;
Euler(int n){
comp.resize(n + 1);
for(int i = 2; i <= n; i++){
if(!comp[i]) primes.emplace_back(i);
for(int j = 0; i * primes[j] <= n; j++){
comp[i * primes[j]] = true;
if(!(i % primes[j])) break;
}
}
}
};
int qmi(int a, int k, int p){
int res = 1;
while(k){
if(k & 1) res = res * a % p;
a = a * a % p;
k >>= 1;
}
return res;
}
int inv(int a){
return qmi(a, mod - 2, mod);
}
constexpr int M = 1e6 + 10;
vector<int> fact(M);
void init(){
fact[0] = 1;
for(int i = 1; i < M; i++){
fact[i] = fact[i - 1] * i % mod;
}
}
void solve(){
int n; cin >> n;
Euler sieve(n);
int p = sieve.primes.size();
int c = n - p;
int res = 0;
int k = 0;
for(int i = 0; i < n; i++){
if(i == 0 || sieve.comp[i + 1]){
res += (k * (k + 1) / 2 + (p - k) * (p - k + 1) / 2) % mod;
res %= mod;
}
else k++;
}
res *= fact[n] * inv(p + 1) % mod;
res %= mod;
res += c * (c - 1) % mod * inv(4) % mod * fact[n] % mod;
res %= mod;
cout << res << '\n';
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
init();
solve();
return 0;
}