题解:CF938E Max History
题意
给定数组
- 初始时
f_{A}=0 ,M=1 ; - 对于每个
2 \leq i \leq n ,如果A_{M} < A_{i} ,则令f_{A}=f_{A}+A_{M} ,并将M=i 。
思路
总贡献类问题有两种思路:枚举方案算贡献和枚举贡献算方案。
显然对于每一个
先将
然后是一些数学推导参考的题解,提出公共部分,得:
把排列变组合,提出
然后就很高兴地发现后面是组合数求和,朱世杰恒等式代进去:
最后对于每个
代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1000005, Mod = 1e9 + 7;
int A[N], Fac[N] = {1}, Inv[N] = {1};
int Pow(int x, int k) {
int Res=1;
for(;k;k>>=1, x=(ll)x*x%Mod) if(k&1) Res=(ll)Res*x%Mod;
return Res;
}
int C(int n, int m) {
return (ll)Fac[n]*Inv[m]%Mod*Inv[n-m]%Mod;
}
int main() {
int n; cin>>n;
for(int i=1;i<=n;i++) Fac[i]=(ll)Fac[i-1]*i%Mod;
Inv[n]=Pow(Fac[n], Mod-2);
for(int i=n;i>=1;i--) Inv[i-1]=(ll)Inv[i]*i%Mod;
for(int i=1;i<=n;i++) cin>>A[i];
sort(A+1, A+1+n);
int Ans=0;
for(int i=1, Last=0;i<=n && A[i]!=A[n];i++) {
if(A[Last]!=A[i]) Last=i;
Ans=(Ans+(ll)A[Last]*Fac[n-Last]%Mod*Fac[Last-1]%Mod*C(n, n-Last+1))%Mod;
}
cout<<Ans<<endl;
return 0;
}
/*
\sum_{j = 0}^{i-1} A_i*A(i-1, j)*(n-j-1)!
*/