题意:
给你n个数,求
a[i]<=1e9, n<=1000
题解:
考虑算每个数最大的时候的贡献,即这个数*这个数最大时的方案数。
先按a[i]从小到大排序。
对于每个a[i], 里面包含了a[i] - a[i-1] 个值。对于每个值x,方案数即为 所有数最多为x时的方案数减去所有数最多为x-1时的方案数。
最后推出来需要求一下幂和,即1^k+2^k+...n^k。这个可以用伯努利数也可以用拉格朗日插值。
伯努利数预处理时的复杂度为k^2, 查询1^k+2^k+...n^k时的复杂度为k.
代码:
#include<bits/stdc++.h>
#define For(G,x) for(int h=G.head[x],o=G.V[h]; h; o=G.V[h=G.to[h]])
#define fir first
#define sec second
#define pii pair<int,int>
#define debug(x) cout<<#x<<" = "<<x<<endl;
using namespace std;
const int MAXN = 1e5 + 5;
const int MOD = 1e9 + 7;
#define ll long long
ll inv[MAXN],fac[MAXN],invf[MAXN],B[MAXN];
int a[MAXN];
inline ll C(ll x,ll y) {
return fac[x] * invf[y] % MOD * invf[x-y] % MOD;
}
ll pow_(ll x,ll y) {
x %= MOD;
ll r=1;
while(y) {
if(y & 1) r = r * x % MOD;
x = x * x % MOD;
y >>= 1;
}
return r;
}
//预处理伯努利数
void init(){
invf[0] = inv[0] = inv[1] = fac[0] = fac[1] = 1;
for(ll i=1; i<=2005; i++) fac[i] = fac[i-1]* i % MOD;
for(int i=2; i<=2005; i++) inv[i] = (MOD-MOD/i) * inv[MOD%i] % MOD;
for(int i=1; i<=2005; i++) invf[i] = invf[i-1] * inv[i] % MOD;
B[0] = 1;
for(int i=1; i<=2001; i++) {
B[i]=0;
for(int j=0; j<i; j++) B[i] = (B[i] + C(i+1,j) * B[j]) % MOD;
B[i]=((B[i] * -inv[i+1]) % MOD + MOD)%MOD;
}
}
//求1^k+2^k+...n^k
ll getv(int n, int k) {
ll Ans=0;
for(int i=1; i <= k+1; i++) Ans=(Ans + C(k+1,i) * B[k+1-i] % MOD *pow_(n+1,i)) % MOD;
Ans = Ans * inv[k+1] % MOD;
return Ans;
}
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
#endif
int n;
init();
while(~scanf("%d", &n)) {
ll ans = 0;
int pre = 0;
ll base = 1, ext = 0;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
for(int i = 1; i <= n; i++) {
if(a[i] == a[i - 1]) continue;
ll t = (a[i] * pow_(a[i], n - i + 1) - (getv(a[i] - 1, n - i + 1)
- getv(pre, n - i + 1)) + MOD) % MOD * base % MOD;
t = (t - (pre + 1) * ext % MOD + MOD) % MOD;
ans = (ans + t) % MOD;
ext = pow_(a[i], n - i + 1) * base % MOD;
base = base * a[i] % MOD;
pre = a[i];
}
printf("%lld\n", ans);
}
}