传送门

先算出所需亵渎个数,观察就可以发现,有一个小细节,如果从开始有一段连续的空位,应该把它去掉,因为不会需要多余的亵渎。

我们计算每一次亵渎的贡献,第一次亵渎我们认为是在位置。显然第一次的贡献是 空位的贡献。

之后我们考虑在一个空位上使用亵渎,设空位为,那么有贡献的区间为。贡献为

最后我们减去空位多算的贡献即可。

考虑计算,可利用拉格朗日插值,参考这里

#include<bits/stdc++.h>
#define ts cout<<"ok"<<endl
#define int long long
#define hh puts("")
#define mo 1000000007
using namespace std;
int n,m,a[55],k,f[55],pre[55],suf[55],fac[55],ans;
map<int,int> ma;
inline int read(){
    int ret=0,ff=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') ff=-ff;ch=getchar();}
    while(isdigit(ch)){ret=(ret<<3)+(ret<<1)+ch-'0';ch=getchar();}
    return ret*ff;
}
void write(int x){
    if(x>9) write(x/10);
    putchar(x%10+48);
}
inline int ksm(int x,int y){
    int res=1;
    while(y){
        if(y&1) res=res*x%mo;
        y>>=1;
        x=x*x%mo;
    }
    return res;
}
inline int calc(int p){
    if(p<=k+2) return f[p];
    int res=0;
    pre[0]=1;
    for(int i=1;i<=k+2;i++) pre[i]=pre[i-1]*(p-i)%mo;
    suf[k+3]=1;
    for(int i=k+2;i>=1;i--) suf[i]=suf[i+1]*(p-i)%mo;
    for(int i=1;i<=k+2;i++){
        int x=pre[i-1]*suf[i+1]%mo;
        int fu=((k+2-i)&1)?-1:1;
        int y=fac[i-1]*fac[k+2-i]*fu%mo;
        res=(res+f[i]*x%mo*ksm(y,mo-2)%mo)%mo;
    }
    return (res+mo)%mo;
}
signed main(){
    fac[0]=1;
    for(int i=1;i<=52;i++) fac[i]=fac[i-1]*i%mo;
    int T=read();
    while(T--){
        n=read(),m=read();
        k=m+1;
        ma.clear();
        for(int i=1;i<=m;i++) a[i]=read(),ma[a[i]]=1;
        sort(a+1,a+m+1);
        while(ma[n]) n--,k--,m--;
        for(int i=1;i<=k+2;i++) f[i]=(f[i-1]+ksm(i,k))%mo;
        ans=calc(n);
        for(int i=1;i<=m;i++) ans=(ans-ksm(a[i],k))%mo;
        for(int i=1;i<=m;i++) ans=(ans+calc(n-a[i]))%mo;
        for(int i=1;i<=m;i++)
            for(int j=i-1;j>=1;j--)
                ans=(ans-ksm(a[i]-a[j],k))%mo;
        write((ans+mo)%mo),hh;
    }
    return 0;
}