【模板】康托展开

题目描述

求 $1\sim N$ 的一个给定全排列在所有 $1\sim N$ 全排列中的排名。结果对 $998244353$ 取模。

对于$100%$数据,$1\le N\le 1000000$。

分析

感觉康拓展开有点数位dp的影子捏。

懒得写了

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
36
37
38
39
40
41
42
43
44
45
46
#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1e6 + 5;
const int mod = (114514+114514)*((1+1)*4*514+((11+4)*(5-1)*4+1-14+5+14))+(114514+(114*51*4+(11*45*(1+4)+1*14+5*14)));

int n, ans;
int fac[N], a[N];

struct bitree{
int c[N], res;
inline int lb(int x) { return x & (-x); }
inline void add(int x, int v){
for (; x <= n; x += lb(x))
c[x] += v;
}
inline int find(int x){
for (res = 0; x; x -= lb(x))
res += c[x];
return res;
}
inline int find(int x, int y){
return find(y) - find(x - 1);
}
}tr;

signed main(){

cin >> n, fac[0] = 1;
for (int i = 1; i <= n; i++)
cin >> a[i], tr.add(i, 1);

for (int i = 1; i <= n; i++)
fac[i] = fac[i - 1] * i % mod;

for (int i = 1; i <= n; i++){
ans = (ans + tr.find(a[i] - 1) * fac[n - i]) % mod;
tr.add(a[i], -1);
}

cout << ans + 1;


return 0;
}

Written with StackEdit中文版.