康託展開
阿新 • • 發佈:2020-12-04
康託展開
利用康託展開,可以求得全排列的序列號
康託展開有公式: \(ans=\sum_{i=1}^{n}{k \times (i-1)!} + 1\)
其中的 \(k\) 即為該點構成的逆序對的數量
code
#include<iostream> #include<cstdio> #include<math.h> #include<cstring> #include<queue> #include<vector> #include<bitset> #include<map> #include<algorithm> #define ll long long const ll mod=998244353; const ll maxn=1000010; ll n,ans; ll a[maxn],tre[maxn],b[maxn],f[maxn]; inline ll lowbit(ll x) { return x & (-x); } inline void upd(ll x,ll w) { while(x<=n) { tre[x]+=w; x+=lowbit(x); } } inline ll sum(ll x) { ll sum=0; while(x) { sum+=tre[x]; x-=lowbit(x); } return sum; } inline void pre() { f[0]=1; for(int i=1;i<=n;i++) { f[i]=f[i-1]*i%mod; } } int main(void) { scanf("%lld",&n); for(int i=1;i<=n;i++) { scanf("%lld",a+i); } pre(); for(int i=n;i>=1;i--) { (ans+=sum(a[i]-1)%mod*f[n-i]%mod)%=mod; upd(a[i],1); } printf("%lld\n",(ans+1)%mod); return 0; }