Description
给出一个长度为n的排列
Input
第一行一整数
Output
输出字典序比p小的排列的逆序对数之和,结果模
Sample Input
2
2 1
Sample Output
1
Solution
记n个数的所有排列逆序对为
然后考虑当一个排列前i−1个数字和p相同,第
1.后
2.前i−1个数产生的逆序对数就按照正常树状数组求逆序对数然后乘上(n−i)!即可
3.前i−1个数对后n−i+1个数产生的逆序对数=后
4.第i个数对后
当第i个数取
当第i个数取
当第i个数取
当第i个数取
故当地i个数取小于
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=1000005;
const int mod=1000000007;
int fact[maxn];
void init(int n=1e6)
{
fact[0]=1;
for(int i=1;i<=n;i++)fact[i]=(ll)i*fact[i-1]%mod;
}
void add(int &x,int y)
{
x=x+y>=mod?x+y-mod:x+y;
}
struct BIT
{
#define lowbit(x) (x&(-x))
int b[maxn],n;
void init(int _n)
{
n=_n;
for(int i=0;i<=n;i++)b[i]=0;
}
void update(int x,int v)
{
while(x<=n)
{
add(b[x],v);
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=0;
while(x)
{
add(ans,b[x]);
x-=lowbit(x);
}
return ans;
}
}bit;
int f(int n)
{
if(n<2)return 0;
int res=(ll)n*(n-1)/2%mod;
return (ll)fact[n-2]*res%mod*res%mod;
}
int n,p[maxn];
int main()
{
init();
while(~scanf("%d",&n))
{
bit.init(n);
for(int i=1;i<=n;i++)scanf("%d",&p[i]);
int ans=0,sum=0;
for(int i=1;i<=n;i++)
{
int num=bit.sum(p[i]);
int temp=(ll)(p[i]-1-num)*(p[i]-2-num)/2%mod;
add(ans,(ll)temp*fact[n-i]%mod);
add(ans,(ll)sum*fact[n-i]%mod*(p[i]-1-num)%mod);
add(ans,(ll)f(n-i)*(p[i]-1-num)%mod);
add(ans,p[i]-1-num);
bit.update(p[i],1);
add(sum,p[i]-1-num);
}
printf("%d\n",ans);
}
return 0;
}