CF938E Max History 组合计数
套路:对于这种计算所有情况价值和的问题计算每一个点对答案的贡献.
我们发现,位置 $i$ 能对答案贡献 $val[i]$,当且仅当 $i$ 是前缀最大值,且 $i$ 不等于序列中最大元素.
我们不妨考虑哪些点大于等于 $val[i]$ 的位置,那么 $val[i]$ 能产生贡献的话显然要求 $i$ 在这些位置中排在最靠前.
这样的话组合就好列了:$\binom{n}{n-num}\times num!\times (n-num-1)!$
code:
#include <cstdio>
#include <algorithm>
#define N 1000007
#define ll long long
#define mod 1000000007
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int inv[N],fac[N],A[N],val[N],mn[N],n;
int qpow(int x,int y)
{
int tmp=1;
for(;y;y>>=1,x=(ll)x*x%mod)
if(y&1) tmp=(ll)tmp*x%mod;
return tmp;
}
int C(int x,int y) { return (ll)fac[x]*inv[y]%mod*inv[x-y]%mod; }
int main()
{
// setIO("input");
int i,j,ans=0;
scanf("%d",&n),inv[0]=fac[0]=1;
for(i=1;i<=n;++i) fac[i]=(ll)fac[i-1]*i%mod,inv[i]=qpow(fac[i],mod-2);
for(i=1;i<=n;++i) scanf("%d",&val[i]),A[i]=val[i];
sort(A+1,A+1+n);
for(i=1;i<=n;++i) mn[i]=lower_bound(A+1,A+1+n,val[i])-A-1;
for(i=1;i<=n;++i)
{
if(val[i]==A[n]) continue;
int tmp=(ll)C(n,n-mn[i])*fac[mn[i]]%mod*fac[n-mn[i]-1]%mod;
ans=(ll)(ans+(ll)tmp*val[i]%mod)%mod;
}
printf("%d\n",ans);
return 0;
}

浙公网安备 33010602011771号