link:https://codeforces.com/contest/938/problem/E
題意:給一個序列 \(a\) ,按如下方式計算 \(f_a\):
- 初始 \(f_a=0,M=1\)
- 對每個 \(2\leq i\leq n\),如果 \(a_M<a_i\),\(f_a\to f_a+a_M\),然後 \(M=i\)
對所有 \(a\) 的排列計算 \(f_a\) 並其在模 \(10^9+7\) 下的和。
\(1\leq n\leq 10^6,1\leq a_i\leq 10^9\)
對每個序列的 \(f_a\) 的值是一段從 \(a_1\) 開始的上升序列的和,並且 \(a\) 的最大值沒有貢獻,反過來考慮每個 \(a_i<\max(a)\) 的貢獻:
- 設 \(a_i\) 在位置 \(j\) 處出現,要產生貢獻當且僅當前面的數嚴格比 \(a_i\) 小,假設這樣的數有 \(s_i\) 個,則有 \(s_i!/(s_i-(j-1))!\) 种放法,後面的數隨便放,有 \((n-j)!\) 種,$$\sum_{j=1}^n \frac{s_i!(n-j)!}{(s_i-j+1)!}=s_i!\sum_{j=1}^n \frac{(n-j)!}{(s_i-j+1)!}\frac{(n-1-s_i)!}{(n-1-s_i)!}=s_i!(n-1-s_i)! \sum_{j=1}^n \binom{n-j}{n-1-s_i}$$經典上指標求和,翻轉指標,從\(\binom{n}{k}=\binom{n-1}{k}+\binom{n-1}{k-1}\)與\(\binom{n}{-1}=0\),為 可以倒推:$$s_i!(n-1-s_i)!\sum_{j=0}^{n-1}\binom{j}{n-1-s_i}=s_i!(n-1-s_i)!\binom{n}{n-s_i}$$
- 對每個值計算貢獻即可
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
const int N=1e6+55;
const int MOD=1e9+7;
int ksm(int a,int b){
int ret=1;a%=MOD;
for(;b;b>>=1,a=(ll)a*a%MOD)if(b&1)ret=(ll)ret*a%MOD;
return ret;
}
int n,a[N],fact[N],inv_fact[N];
map<int,int> S;
int C(int n,int k){
if(k>n)return 0;
return (ll)fact[n]*inv_fact[k]%MOD*inv_fact[n-k]%MOD;
}
int main(){
fastio;
fact[0]=1;
rep(i,1,N-5)fact[i]=(ll)fact[i-1]*i%MOD;
inv_fact[N-5]=ksm(fact[N-5],MOD-2);
for(int i=N-5;i>=1;i--)inv_fact[i-1]=(ll)inv_fact[i]*i%MOD;
cin>>n;
int mx=0;
rep(i,1,n){
cin>>a[i];
S[a[i]]++;
mx=max(mx,a[i]);
}
int cnt=0,ans=0;
for(auto [x,c]:S)if(x!=mx){
ans=(ans+(ll)x*fact[cnt]%MOD*fact[n-cnt-1]%MOD*C(n,n-cnt)%MOD*c%MOD)%MOD;
cnt+=c;
}
cout<<ans;
return 0;
}