本场比赛难度不大,也是本人第一次AK,最后一题用组合数学+推公式,本篇博客主要讲解最后一题的思路
G-小红的陡峭值(五)(hard)_牛客周赛 Round 84
思路:本题要我们求p/q mod M ,即p*(q的逆),q为排列数,我们可以很容易得到,即 n!,但分子为所有排列的陡峭值之和,暴力做法肯定是不行的,于是我们可以通过绝对值的性质:若a2>a1,则|a1-a2|=|a2-a1|=a2-a1,先将数组a进行升序排序,我们可以计算a[i-1]a[i]这对相邻元素会出现在多少种不同的排列中,这里我们可以使用高中学的排列组合来计算,从n个元素中拿出去2个元素,还剩下n-2个元素,那么这n-2个元素就有(n-2)!种摆放方式,再将a[i-1]a[i]插入n-1个空中的任意一个,就可以得到a[i-1]a[i]在(n-2)!*(n-1)=(n-1)!个排列中做出了贡献,而a[i]a[i-1]的贡献与a[i-1]a[i]一样,那么我们要计算出(a[i]-a[i-1])+(a[i]-a[i-2])+(a[i]-a[i-3])+...+(a[i]-a[1])的和,那么这个式子化简一下就是(i-1)*a[i]-pre[i-1],最终我们得到的结果p/q= =
Code:
int n;
int qmi(int a,int b)
{
int res=1;
while(b)
{
if(b&1)res=res*a%mod;
b>>=1;
a=a*a%mod;
}
return res;
}
void solve()
{
cin >> n;
vector<int> v(n+1);
for(int i=1;i<=n;i++) cin>>v[i];
sort(v.begin()+1,v.end());
vector<int> pre(n+1,0);
for(int i=1;i<=n;i++)
{
pre[i]=(pre[i-1]+v[i]%mod)%mod;
}
int S=0;
for(int i=1;i<=n;i++)
{
int b=((v[i]%mod)*(i-1+mod)%mod)%mod;
b=(b-pre[i-1]+mod)%mod;
S=(S+b)%mod;
}
int num=(2*S)%mod;
int inv=qmi(n,mod-2);
int ans=num*inv%mod;
cout<<ans<<endl;
}