对于连续的排列直接的逆序 打表或者首先就可以看出规律
设f(n)表示n个数时 每个排列所对应的逆序数
显然有 f(1)=1, f(2)=0,1 , f(3)=0,1,1,2,2,3 , f(4)= 0,1,1,2,2,3, 1,2,2,3,3,4 , 2,3,3,4,4,5 , 3,4,4,5,5,6
即为f(n-1)的所有的数为一组 扩展成n组 第一组为f(n-1) 后面每组比前一组中所有的数大1
所以我们可以预先把dp[i](表示f(i)的总和)用cnt[i](表示f(i)的个数 即i的阶乘)递推的处理出来
而对于3,1,4,5,2 这样的一组数时
首先对于3这位 要加上以1 和 2开头时f(n)的值 即 加上2*dp[4]+1*cnt[4] (4为后面剩余的个数,2为比3小的个数 ,1为(比3小的个数-1)的前缀和)
而考虑下一位时 这时已经假定3已经选定 (第一位为1和2的已经加完了) 所以3是对后面有影响的 影响为2(比3小的个数) 而当我们考虑第3位的数字4的时候 因为3已经固定
所以4要相当于3来处理 所以我们可以用一个树状数组来维护
个人感觉这个dp我想麻烦了 没有想到很优美的递推方法 但这个思路还是蛮好理解的(就是求它之前的所以排列的逆序数) 不足就是要维护和记录好多东西(>﹏<)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#define scnaf scanf
#define cahr char
#define bug puts("bugbugbug");
using namespace std;
typedef long long ll;
const int mod=1000000007;
const int maxn=1e5+5;
const int inf=1e9;
int N;
const int NV=105;
int c[NV];
inline int lowbit(int t)
{
return t&(-t);
}
void update(int x,int v)
{
while(x<=N)
{
c[x]+=v;
x+=lowbit(x);
}
}
int query(int x)
{
int ans=0;
while(x>0)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
int findkth(int k)
{
int idx = 0;
for(int i=20; i>=0; i--)
{
idx |= 1 << i;
if(idx <= N && c[idx] < k)
k -= c[idx];
else idx ^= 1 << i;
}
return idx + 1;
}
ll dp[105],cnt[105];
void init()
{
dp[1]=0;
cnt[1]=1;
for(int i=2;i<=100;i++)
{
dp[i]=dp[i-1]*i%mod;
dp[i]=(dp[i]+cnt[i-1]*(i*(i-1)/2)%mod)%mod;
cnt[i]=cnt[i-1]*i%mod;
}
}
int a[105];
int main()
{
init();
int n;
while(~scanf("%d",&n))
{
N=n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
ll ans=0;
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++) update(i,1);
ll fuck=0;
for(int i=1;i<=n;i++)
{
int num=query(a[i]);
ans += dp[n-i] * (num-1) % mod + cnt[n-i] *((num-1)*(num-2)/2)%mod;
ans%=mod;
ans += fuck * (num-1) % mod * cnt[n-i] %mod;
ans%=mod;
fuck=fuck+num-1;
update(a[i],-1);
}
memset(c,0,sizeof(c));
printf("%lld\n",ans);
}
}