康托展开
利用康托展开,可以求得全排列的序列号
康托展开有公式: (ans=sum_{i=1}^{n}{k imes (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
",(ans+1)%mod);
return 0;
}