[日常训练]挂科


Description

小$Y$非常喜欢学习,但却又经常翘课,现在期末来临,他要挂科了。
期末考中小$Y$一共考了$n$门课,这$n$门课的分数为$a_i$,而只要有一门课不及格,他就会留级。
现在小$Y$不知道每门课及格所要求的分数,他只知道他每一门课的分数都要严格高于这门课的要求分数。不过,小$Y$有个厉害的技能,那就是换成绩,具体地说,他可以将任意两门课的成绩互换,且他可以互换任意次。
现在他想知道,有多少种及格要求分数能不让他挂科(及格要求分数自然是非负整数)。
由于答案数可能很大,你只需要输出模$10^9+7$。

Input

第一行一个整数$T$,表示数据组数。
接下来$T$行每行一组数据。每组数据以一个整数$n$开头,表示课程数,后面$n$个整数$a_i$表示小$Y$这$n$门课的成绩。

Output

共$T$行,第$i$行表示第$i$组数据的答案。

Sample Input

4
2 1 2
3 2 5 3
4 1 2 3 4
4 9 8 3 5

Sample Output

3
74
125
4371

HINT

$1\;\leq\;n\;\leq\;1000,0\;\leq\;a_i\;\leq\;10^9,T\;\leq\;5$.

Solution

因为可以交换任意次,所以先将$a_i$从小到大排序.

$f[i]$表示处理到第$i$个数,前$i$个数合法的方案数.

$f[i]=a_i^i-\sum_{j=1}^{i-1}(f[j-1]\;\times\;(a_i-a_j)^{i-j+1}\;\times\;C_i^{j-1})$.

即总方案数-不合法的方案数.

枚举$j$,表示之前合法,在第$j$位不合法.之前合法的方案数为$f[j-1]$第$j$位到第$i$位不合法,只能填$[a_j,a_i)$,这种情况在前$i$位一共有$C_i^{j-1}$种分布.

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 1005
#define P 1000000007
#define M 1000000007ll
using namespace std;
typedef long long ll;
ll fac[N],a[N],f[N],ans;
int n,t;
inline ll po(ll x,int k){
    ll ret=1ll;
    while(k){
        if(k&1) ret=ret*x%M;
        x=x*x%M;k>>=1;
    }
    return ret;
}
inline ll rev(ll x){
    if(x==1ll) return 1ll;
    ll ret=1ll;int k=P-2;
    while(k){
        if(k&1) ret=ret*x%M;
        x=x*x%M;k>>=1;
    }
    return ret;
}
inline ll c(int n,int m){
    return fac[n]*rev(fac[n-m])%M*rev(fac[m])%M;
}
inline void Aireen(){
    scanf("%d",&t);
    fac[0]=1ll;
    for(int i=1;i<=1000;++i)
        fac[i]=fac[i-1]*(ll)(i)%M;
    f[0]=1ll;
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
            scanf("%lld",&a[i]);
        sort(a+1,a+1+n);
        for(int i=1;i<=n;++i){
            f[i]=po(a[i],i);
            for(int j=1;jj)
                f[i]=(f[i]-f[j-1]*po(a[i]-a[j],i-j+1)%M*c(i,j-1)%M+M)%M;
        }
        printf("%lld\n",f[n]);
    }
}
int main(){
    freopen("godie.in","r",stdin);
    freopen("godie.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}