链接:
https://www.nowcoder.com/acm/contest/139/F
来源:牛客网
题目描述
Given a1, a2, …, an, find
modulo (109+7).
输入描述:
The input consists of several test cases and is terminated by end-of-file. The first line of each test case contains an integer n. The second line contains n integers a1, a2, ..., an.
输出描述:
For each test case, print an integer which denotes the result.
示例1
输入
复制
2 1 2 5 2 3 3 3 3
输出
复制
3 453
备注:
* 1 ≤ n ≤ 1000 * 1 ≤ ai ≤ 109 * The number of test cases does not exceed 10.
转载自
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long ll;
const int maxn=1010;
const int mod=1e9+7;
ll val[maxn],b[maxn];
/*
因为数字太大,根本不可能一项一项的求出来结果,就算是
ai--a(i+1),也是不可能的
但是可以直接用 n-i+1项,直接 预估出来结果(后悔matlab没认真学)
*/
//拉格朗日插值模版
/**************************************** head ****************************************/
namespace polysum {
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
const int D=2010;
ll a[D],f[D],g[D],p[D],p1[D],p2[D],b[D],h[D][2],C[D];
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll calcn(int d,ll *a,ll n) { // a[0].. a[d] a[n]
if (n<=d) return a[n];
p1[0]=p2[0]=1;
rep(i,0,d+1) {
ll t=(n-i+mod)%mod;
p1[i+1]=p1[i]*t%mod;
}
rep(i,0,d+1) {
ll t=(n-d+i+mod)%mod;
p2[i+1]=p2[i]*t%mod;
}
ll ans=0;
rep(i,0,d+1) {
ll t=g[i]*g[d-i]%mod*p1[i]%mod*p2[d-i]%mod*a[i]%mod;
if ((d-i)&1) ans=(ans-t+mod)%mod;
else ans=(ans+t)%mod;
}
return ans;
}
void init(int M) {
f[0]=f[1]=g[0]=g[1]=1;
rep(i,2,M+5) f[i]=f[i-1]*i%mod;
g[M+4]=powmod(f[M+4],mod-2);
per(i,1,M+4) g[i]=g[i+1]*(i+1)%mod;
}
//要求m次的方程,Y=a[0]...a[m]是 X=0...m对应的值,
//预估sum[n-1]的值
ll polysum(ll m,ll *a,ll n) { // a[0].. a[m] \sum_{i=0}^{n-1} a[i]
ll b[D];
for(int i=0;i<=m;i++) b[i]=a[i];
b[m+1]=calcn(m,b,m+1);
rep(i,1,m+2) b[i]=(b[i-1]+b[i])%mod;
return calcn(m+1,b,n-1);
}
ll qpolysum(ll R,ll n,ll *a,ll m) { // a[0].. a[m] \sum_{i=0}^{n-1} a[i]*R^i
if (R==1) return polysum(n,a,m);
a[m+1]=calcn(m,a,m+1);
ll r=powmod(R,mod-2),p3=0,p4=0,c,ans;
h[0][0]=0;h[0][1]=1;
rep(i,1,m+2) {
h[i][0]=(h[i-1][0]+a[i-1])*r%mod;
h[i][1]=h[i-1][1]*r%mod;
}
rep(i,0,m+2) {
ll t=g[i]*g[m+1-i]%mod;
if (i&1) p3=((p3-h[i][0]*t)%mod+mod)%mod,p4=((p4-h[i][1]*t)%mod+mod)%mod;
else p3=(p3+h[i][0]*t)%mod,p4=(p4+h[i][1]*t)%mod;
}
c=powmod(p4,mod-2)*(mod-p3)%mod;
rep(i,0,m+2) h[i][0]=(h[i][0]+h[i][1]*c)%mod;
rep(i,0,m+2) C[i]=h[i][0];
ans=(calcn(m,C,n)*powmod(R,n)-c)%mod;
if (ans<0) ans+=mod;
return ans;
}
} // polysum::init();
ll pow_(ll base,int n,int mod){
ll ans=1;
while(n){
if(n&1)ans=(ans*base)%mod;
base=(base*base)%mod;
n>>=1;
}
return ans;
}
int main(){
int n;
polysum::init(1010);
while(scanf("%d",&n)==1){
for(int i=1;i<=n;i++){
scanf("%lld",&val[i]);
}
sort(val+1,val+n+1);
val[0]=0;
ll ans=0,now=1;
for(int i=1;i<=n;i++){
if(val[i]==val[i-1]){
now=(now*val[i])%mod;
continue;
}
b[0]=0;
for(int j=1;j<=n-i+1;j++){
b[j]=j*(pow_(j,n-i+1,mod)+mod-pow_(j-1,n-i+1,mod))%mod;
}
ll tmp=(polysum::polysum(n-i+1,b,val[i]+1)+mod-polysum::polysum(n-i+1,b,val[i-1]+1))%mod;
ans=(ans+now*tmp%mod)%mod;
now=now*val[i]%mod;
}
printf("%lld\n",ans);
}
return 0;
}