题意:开始m=1,从2->n枚举i,如果a[i]>a[m],ans+=a[m],求a的所有排列中ans之和。
如果我们将a数组从大到小排序,最大的数后面没有比它的数了,所以答案永远不会计算它,接着次大的数字如果想要被计算,那么它必须在最大数的前面,那么最大数在前面与次大数在前面概率相等,均为1/2,那么次大数对所有答案的贡献就是a[2]*n!/2,接着第三大的数字如果想被计算,必须在最大与次大之前,它在最前的概率为1/3,所以它对最终答案的贡献就是a[3]*n!/3,没有重复的答案就是这样计算。
如果有重复元素的话,那么它后面可能会存在与它相等的数字,所以贡献就是这个数字出现的次数*这个数字的值/这个数字在排序后数组出现的最后位置,因为每一个数字要被计算的条件是前面没有大于等于它的数字。
如果从小到大排序的话比较方便计算。
下附AC代码。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 1000005
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll n;
ll a[maxn];
ll quickpow(ll p,ll k)
{
ll ans=1;
while(k)
{
if(k&1)
ans=(ans*p)%mod;
p=(p*p)%mod;
k>>=1;
}
return ans;
}
int main()
{
scanf("%I64d",&n);
ll temp=1;
for(ll i=1;i<=n;i++)
{
scanf("%I64d",&a[i]);
temp*=i;
temp%=mod;
}
sort(a+1,a+1+n);
ll ans=0;
for(ll i=1;i<=n;i++)
{
if(a[i]==a[n]) break;
ll j;
for(j=i;a[j]==a[i];j++);
ans+=(((a[i]*(j-i))%mod*temp)%mod*quickpow(n-i+1,mod-2)%mod);
ans%=mod;
i=j-1;
}
printf("%I64d\n",ans);
}