设
S=∏ki=1pi,n=∑xipi
S
=
∏
i
=
1
k
p
i
,
n
=
∑
x
i
p
i
。
可以发现
k
k
最多只有 。
先将
n
n
减去 ,保证
lcm=S
l
c
m
=
S
。
将
xi
x
i
表示为
a⋅Spi+b ( b<Spi )
a
·
S
p
i
+
b
(
b
<
S
p
i
)
,这样每一组
(a,b)
(
a
,
b
)
都是一种方案。
将
n
n
也拆分成 和
n mod S
n
m
o
d
S
两部分。显然
n mod S
n
m
o
d
S
只能用
b
b
填。枚举 中有几个由
b
b
<script type="math/tex" id="MathJax-Element-82">b</script> 填,多重背包预处理下,剩下的就可以直接算了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2000010;
const int M=1000000007;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
inline void Read(ll& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
ll n;
int k,m,T,s;
int cnt;
int Ans;
int p[N],num,sum;
int inv[10];
int a[10];
int f[N<<3],g[N<<3],mx;
bool b[N];
inline void Add(int& x,int y){
x=(x+y)%M;
}
inline bool Init(){
for(int i=2;i<=s;i++){
if(!b[i]){
p[++num]=i;
if(!(s%i)){
sum+=i;a[++cnt]=i;
if(1ll*i*i<=s&&!(s%(i*i)))return 0;
}
}
int t;
for(int j=1;j<=num&&(t=p[j]*i)<=s;j++){
b[t]=1;
if(!(i%p[j]))break;
}
}
inv[0]=inv[1]=1;
for(int i=2;i<=9;i++)inv[i]=1ll*inv[M%i]*(M-M/i)%M;
for(int i=3;i<=9;i++)inv[i]=1ll*inv[i-1]*inv[i]%M;
return 1;
}
inline void DP(){
mx=cnt*s;
f[0]=1;
for(int i=1;i<=cnt;i++){
for(int j=0;j<a[i];j++){
int t=0;
for(int k=j;k<=mx;k+=a[i]){
Add(t,f[k]);
if(k>=s)Add(t,-f[k-s]);
g[k]=t;
}
}
memcpy(f,g,sizeof(g));
}
}
inline int C(ll n,int m){
int Ans=1;
for(ll i=n-m+1;i<=n;i++)Ans=i%M*Ans%M;
Ans=1ll*Ans*inv[m]%M;
return Ans;
}
int main(){
Read(s);Read(T);
if(!Init()){
while(T--)printf("0\n");
return 0;
}
DP();
while(T--){
Read(n);
n-=sum;
if(n<0){
printf("0\n");
continue;
}
Ans=0;
ll x=n/s;int y=n%s;
for(int i=0;i*s+y<=mx&&i<=x;i++)Add(Ans,1ll*f[i*s+y]*C(x-i+cnt-1,cnt-1)%M);
printf("%d\n",(Ans+M)%M);
}
return 0;
}