CF938E Max History
题意:
我们定义f(a)为:
1、开始时,f(a)=0,M=1。
2、对于每个2<=i<=n,如果a[M]<a[i],那么f(a)=f(a)+a[M],M=i。
现在对于一个给定的数组a,求其所有排列的f(a)之和,答案对1e9+7取模。
题解:
计数问题,组合数推导
经常用的组合恒等式:
k∗Cnk=n∗Cn−1k−1k * C_{n}^{k}=n*C_{n-1}^{k-1}k∗Cnk=n∗Cn−1k−1
Ckn∗Cmk=Cmn∗Cm−nm−k(m−k<m−n)C_{k}^{n}*C_{m}^{k}=C_{m}^{n}*C_{m-n}^{m-k}(m-k<m-n)Ckn∗Cmk=Cmn∗Cm−nm−k(m−k<m−n)
∑i=0nCni=2n\sum_{i=0}^{n}C_{n}^{i}=2^n∑i=0nCni=2n
∑k=0n∗(−1)kCnk=0\sum_{k=0}^{n}*(-1)^kC_{n}^{k}=0∑k=0n∗(−1)kCnk=0
Cnk+Cnk+1=Cn+1k+1C_{n}^{k}+C_{n}^{k+1}=C_{n+1}^{k+1}Cnk+Cnk+1=Cn+1k+1
∑k=0mCn+kk=Cn+m+1m\sum_{k=0}^{m}C_{n+k}^{k}=C_{n+m+1}^{m}∑k=0mCn+kk=Cn+m+1m
范德蒙德卷积:
∑i=0kCniCmk−i=Cn+mk\sum_{i=0}^{k}C_{n}^{i}C_{m}^{k-i}=C_{n+m}^{k}∑i=0kCniCmk−i=Cn+mk
代码:
#include<bits/stdc++.h>
#define mod 1000000007
const int maxn = 1000035;int n,ans,cnt,a[maxn],fac[maxn],inv[maxn];int read()
{char ch = getchar();int num = 0, fl = 1;for (; !isdigit(ch); ch=getchar())if (ch=='-') fl = -1;for (; isdigit(ch); ch=getchar())num = (num<<1)+(num<<3)+ch-48;return num*fl;
}
int main()
{n = read();for (int i=1; i<=n; i++) a[i] = read();std::sort(a+1, a+n+1);fac[0] = fac[1] = inv[0] = inv[1] = 1;for (int i=2; i<=n+2; i++){inv[i] = mod-1ll*(mod/i)*inv[mod%i]%mod,fac[i] = 1ll*fac[i-1]*i%mod;}for (int i=1,j; i<=n; i=j+1){for (j=i; a[j+1]==a[i]; j++);//J为 if (j==n) break;//i-1是严格比他小的数 //n-j是严格大于他的数 //j-i+1是与a[i]一样大的数量 cnt = inv[n-i+1];ans = (1ll*ans+1ll*a[i]*(j-i+1)%mod*cnt%mod)%mod;}printf("%d\n",1ll*ans*fac[n]%mod);return 0;
}