这是个求自然数幂和的模板题。难点在于理解题意。
很容易发现 (k=m+1),然后就是 (O(k^2)) 的累计答案。
加上插值求自然数幂和,总复杂度为 (O(k^3))。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define int long long
using namespace std;
typedef long long LL;
const int N=60,M=1000000007,K=1000000;
int m,A[K+9],p[K],cnt,d[K+9];
LL n,a[N],k,pre[K],suf[K],fac[K],inv_fac[K];
int ksm(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=1ll*res*a%M;
b>>=1,a=1ll*a*a%M;
}
return res;
}
void prework(int k)
{
d[1]=1,cnt=0;
for (int i=2;i<=k+2;i++)
A[i]=0;
for (int i=2;i<=k+2;i++)
{
if(!A[i])
A[i]=i,p[++cnt]=i,d[i]=ksm(i,k);
for (int j=1;j<=cnt;j++)
{
if(p[j]>A[i]||p[j]>(k+2)/i)
break;
A[p[j]*i]=p[j];
d[p[j]*i]=1ll*d[p[j]]*d[i]%M;
}
}
// printf("%d
",k+2);
// for (int i=1;i<=k+2;i++)
// printf("%d ",d[i]);puts("");
for (int i=2;i<=k+2;i++)
d[i]=(d[i]+d[i-1])%M;
}
void init()
{
scanf("%lld %lld",&n,&m);
for (int i=1;i<=m;i++)
scanf("%lld",&a[i]);
sort(a+1,a+1+m);
k=m+1;
}
int Get_Sum(LL n,int k)
{
prework(k);
pre[0]=1;
for (int i=1;i<=k+2;i++)
pre[i]=1ll*pre[i-1]*((n-i)%M)%M;
suf[k+3]=1;
for (int i=k+2;i>=1;i--)
suf[i]=1ll*suf[i+1]*((n-i)%M)%M;
fac[0]=1;
for (int i=1;i<=k+2;i++)
fac[i]=1ll*fac[i-1]*i%M;
inv_fac[k+2]=ksm(fac[k+2],M-2);
for (int i=k+1;i>=0;i--)
inv_fac[i]=1ll*inv_fac[i+1]*(i+1)%M;
int ans=0;
for (int i=1;i<=k+2;i++)
ans=(ans+d[i]*pre[i-1]%M*suf[i+1]%M*inv_fac[i-1]%M*inv_fac[k+2-i]%M*(k+2-i&1?-1:1))%M;
return ans;
}
void work()
{
LL ans=0;
a[++m]=n+1;
for (int i=0;i<=m;i++)
for (int j=i+1;j<=m;j++)
ans=(ans+(Get_Sum(a[j]-1-a[i],k)-Get_Sum(a[j-1]-a[i],k))%M)%M;
printf("%lld
",(ans+M)%M);
}
signed main()
{
int T;
scanf("%lld",&T);
while(T--)
{
init();
work();
}
return 0;
}