标签:
hdu 5224 Tom and paper/*hdu 5224 Tom and paper
题意:
给出一个1~n的排列,求所有字典序比它小的排列的逆序对之和,答案对1e9+7取模。
限制:
1 <= n <= 100
思路:
分类讨论
1. 全排列的逆序对之和:n!*n*(n-1)/4
2. 然后遍历每一位,相等的话继续看后面一位,不等的话,看后面小于它的有多少个数,然后乱搞一下。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define LL __int64
#define PB push_back
const int N=105;
const int MOD=1000000007;
LL qpl[N];
LL f[N];
int a[N];
LL inv(LL a,LL m){
LL p=1,q=0,b=m,c,d;
while(b>0){
c=a/b;
d=a; a=b; b=d%b;
d=p; p=q; q=d-c*q;
}
return p<0?p+m:p;
}
void predo(){
f[0]=1;
for(int i=1;i<N;++i)
f[i]=f[i-1]*i%MOD;
LL ny4=inv(4,MOD);
for(int i=1;i<N;++i){
qpl[i]=f[i]*i*(i-1)%MOD*ny4%MOD;
}
}
vector<int> tab[N];
bool vis[N];
void deal(int id,int n,LL &ans){
memset(vis,0,sizeof(vis));
if(tab[id].size()==0) return ;
LL sum1=0,sum2=0;
for(int i=0;i<id;++i){
sum1+=tab[i].size();
vis[a[i]]=1;
}
for(int i=0;i<tab[id].size();++i){
for(int j=1;j<tab[id][i];++j){
if(vis[j]==0) ++sum2;
}
}
ans=(ans+sum1*f[n-1-id]*tab[id].size()+sum2*f[n-1-id])%MOD;
ans=(ans+qpl[n-1-id]*tab[id].size())%MOD;
}
void gao(int n){
LL ans=0;
for(int i=0;i<n;++i){
for(int j=i+1;j<n;++j){
if(a[i]>a[j]) tab[i].PB(a[j]);
}
}
for(int i=0;i<n;++i){
deal(i,n,ans);
}
printf("%I64d\n",ans);
}
void init(){
for(int i=0;i<=N;++i)
tab[i].clear();
}
int main(){
int n;
predo();
while(scanf("%d",&n)!=EOF){
init();
for(int i=0;i<n;++i)
scanf("%d",&a[i]);
gao(n);
}
return 0;
}标签:
原文地址:http://blog.csdn.net/whai362/article/details/45722999