链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
The__Flash 打游戏太投入了,把 PLMM 晾在了一边。为了弥补 PLMM,The__Flash 带着 PLMM 和小喵去看电影。
电影院人山人海,队伍排成一条长长的线,两人一喵只能乖乖排队。队伍长度为 nnn,个体按照队头到队尾的顺序依次编号为 1,2,...,n1,2,...,n1,2,...,n,其中第 iii 个个体的身高为 aia_iai。PLMM 见状想要出题考验一下 The__Flash。
一个长度为 nnn 的序列 aaa 的逆序对个数定义为满足 ai>aj (1≤i<j≤n)a_i>a_j \, (1 \leq i < j \leq n)ai>aj(1≤i<j≤n) 的不同 (i,j)(i,j)(i,j) 的对数,(i1,j1)(i_1,j_1)(i1,j1) 与 (i2,j2)(i_2,j_2)(i2,j2) 不同当且仅当 i1≠i2i_1 \not= i_2i1=i2 或 j1≠j2j_1 \not= j_2j1=j2。
nnn 个个体总共有 n!n!n! 种排队方式,记 Pi(a)P_i(a)Pi(a) 表示序列 aaa 的第 iii 种排队方式,cnt(Pi(a))cnt(P_i(a))cnt(Pi(a)) 表示 PiP_iPi 的逆序对个数。PLMM 想知道 ∑i=1n!cnt(Pi(a))\sum_{i=1}^{n!}{cnt(P_i(a))}∑i=1n!cnt(Pi(a)),由于 The__Flash 傻乎乎的,所以请你帮他回答 PLMM 的问题。
输入描述:
第一行输入一个整数 n (1≤n≤105)n\,(1 \leq n \leq 10^5)n(1≤n≤105)。 第二行输入 nnn 个整数表示 a1,a2,⋯ ,an (1≤ai≤105)a_1,a_2,\cdots,a_n\,(1 \leq a_i \leq 10^5)a1,a2,⋯,an(1≤ai≤105)。
输出描述:
输出一个整数表示答案,由于结果可能太大,因此你只需要输出结果对 109+710^9+7109+7 取模之后的结果。
示例1
输入
复制3 1 2 3
3 1 2 3
输出
复制9
9
思路:算全排列中一共有多少个逆序对,那我们就分别算每个逆序对对总数的贡献
对于两个不相等的数a和b,在全排列中只有两种情况,要么a在前,要么b在前,且这两种情况的排列的数量相等
假设a在前b在后,那么我们就算出含有这个逆序对的排列的个数
对于a来说有n个选择,对于b来说有n-1个选择,但是a在b的前面占所有情况的一半,剩下的(n-2)个数全排列
那么a在b前面的排列就有n*(n-1)/2*(n-2)!个
那么我们只需要算出来逆序对的数量乘上面的柿子就行了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
const int N=1e5+10;
const ll mod=1e9+7;
ll f[N];
ll a[N];
ll ksm(ll a,ll b,ll p){
ll ans=1%p;
while(b){
if(b&1)ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n);
f[0]=1;
for(int i=1;i<=n;i++){
f[i]=f[i-1]*i%mod;
}
ll ans=0;
for(int i=1;i<=n;i++){
int id=lower_bound(a+1,a+1+n,a[i])-a-1;
ans+=id;
}
ll con=ans*n%mod*(n-1)%mod*f[n-2]%mod*ksm(2,mod-2,mod)%mod;
cout<<con<<endl;
//cout<<ans<<endl;
return 0;
}