Description
有n−mn−m只怪物,血量分别为11~中去掉mm个数字,一次亵渎卡的效果是:首先所有怪物血量减一,如果存在怪物血量清零则所有怪物血量继续减一,使用该亵渎卡后,每只怪物对分数的贡献为xkxk,其中xx是该怪物在使用该卡之前的血量,为杀死所有怪物所需的亵渎卡数量,问杀死所有怪物所得分数和
Input
第一行一整数TT表示用例组数,每组用例首先输入两整数,之后输入mm个整数
(1≤T≤10,1≤n≤1013,1≤m≤50,1≤ai≤n,ai≠aj)(1≤T≤10,1≤n≤1013,1≤m≤50,1≤ai≤n,ai≠aj)
Output
输出得分,结果模109+7109+7
Sample Input
2
10 1
5
4 2
1
2
Sample Output
415
135
Solution
假设aa序列升序且,那么第一张亵渎卡的效果会杀掉[1,a1−1][1,a1−1]的所有怪物,而之后的怪物血量变成[1,a2−a1−1],[a2−a1+1,a3−a1−1],...,[am−a1+1,n−a1][1,a2−a1−1],[a2−a1+1,a3−a1−1],...,[am−a1+1,n−a1],显然每使用一次亵渎就会消去一个区间,故k=m+1k=m+1,且第ii次使用亵渎得分为,故问题转化为求自然数幂和,用伯努利数或第二类斯特林数均可求出幂和,此处说一下如何用第二类斯特林数求解,记Sk(n)=∑i=1nikSk(n)=∑i=1nik
考虑恒等式nk=∑i=1kAin⋅S(k,i)nk=∑i=1kAni⋅S(k,i),我们有
注意到
故有
连续i+1i+1个数字相乘必可被i+1i+1整除,故对任意模数均可O(k)O(k)计算Ci+1n+1i+1Cn+1i+1i+1,预处理第二类斯特林数和单次查询时间复杂度均为O(k2)O(k2)
Code
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 105
#define mod 1000000007
int mul(int x,int y)
{
ll z=1ll*x*y;
return z-z/mod*mod;
}
int add(int x,int y)
{
x+=y;
if(x>=mod)x-=mod;
return x;
}
int Pow(int x,int y)
{
int ans=1;
while(y)
{
if(y&1)ans=mul(ans,x);
x=mul(x,x);
y>>=1;
}
return ans;
}
int S[maxn][maxn];
void init(int n=52)
{
S[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=i;j++)
S[i][j]=add(S[i-1][j-1],mul(j,S[i-1][j]));
}
int Solve(ll n,int k)
{
int ans=0;
for(int i=1;i<=k;i++)
{
int res=S[k][i];
for(ll j=n+1-i;j<=n+1;j++)
if(j%(i+1)==0)res=mul(res,j/(i+1)%mod);
else res=mul(res,j%mod);
ans=add(ans,res);
}
return ans;
}
int T,m;
ll n,a[maxn];
int main()
{
init();
scanf("%d",&T);
while(T--)
{
scanf("%lld%d",&n,&m);
for(int i=1;i<=m;i++)scanf("%lld",&a[i]);
sort(a+1,a+m+1);
int ans=0;
for(int i=1;i<=m+1;i++)
{
ans=add(ans,Solve(n-a[i-1],m+1));
for(int j=i;j<=m;j++)ans=add(ans,mod-Pow((a[j]-a[i-1])%mod,m+1));
}
printf("%d\n",ans);
}
return 0;
}