###题目大意:
题面
###思路:
首先你发现一个集合里面的物品可以组合成的总体积必定是
g
c
d
(
v
i
,
p
)
,
i
∈
S
gcd(v_i,p),i\in S
gcd(vi,p),i∈S,于是为了防止重复计算,一个方案用它的gcd来表示。
于是对于每一个物品,可以直接使得
v
i
=
g
c
d
(
v
i
,
p
)
v_i=gcd(v_i,p)
vi=gcd(vi,p),然后我们将p的所有的约数提取出来,做一个dp,dp[i][j]表示前i个物品组合使得gcd为p的第j个约数的方案数。
d
p
[
i
]
[
j
]
=
d
[
i
−
1
]
[
j
]
+
d
p
[
i
]
[
k
]
×
(
2
c
n
t
[
i
]
−
1
)
(
g
c
d
(
v
a
l
[
i
]
,
f
a
c
[
k
]
)
=
=
f
a
c
[
j
]
)
dp[i][j]=d[i-1][j]+dp[i][k]\times(2^{cnt[i]}-1) \ \ \ \ (gcd(val[i],fac[k])==fac[j])
dp[i][j]=d[i−1][j]+dp[i][k]×(2cnt[i]−1) (gcd(val[i],fac[k])==fac[j])
转移的时候没有必要对j枚举上一层的k,因为上一层的每一个k保证只会对应这一层的一个j(我在这里就没有想清楚)。
考虑如何计算答案,因为组成的gcd只会是p的约数,而答案又必须是
w
i
w_i
wi的约数,所以必定是
g
c
d
(
p
,
w
i
)
gcd(p,w_i)
gcd(p,wi)的约数,所以我们只需要对p的每一个约数
d
j
d_j
dj处理
g
c
d
(
p
,
w
i
)
gcd(p,w_i)
gcd(p,wi)为
d
j
d_j
dj的答案就好了。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
typedef long long ll;
using namespace std;
void File(){
freopen("loj2523.in","r",stdin);
freopen("loj2523.out","w",stdout);
}
template<typename T>void read(T &_){
T __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}
template<typename T>void write(T x,char ch){
if(!x){putchar('0');putchar(ch);return;}
ll len=1,y=10;
while(y<=x)y=(y<<1)+(y<<3),++len;
while(len--){
y/=10;
putchar(x/y+48);
x%=y;
}
putchar(ch);
}
const int maxn=1e6+10;
const int maxd=5e3+10;
const ll mod=1e9+7;
int n,q,p,num[maxn],d[maxn],tot,val[maxn],cnt[maxn],w[maxn];
ll dp[maxd][maxd],ans[maxn],Pow[maxn];
map<int,int>mp;
void init(){
read(n); read(q); read(p);
REP(i,1,n)read(val[i]),val[i]=__gcd(val[i],p);
REP(i,1,q)read(w[i]),w[i]=__gcd(w[i],p);
REP(i,1,n)++mp[val[i]];
sort(val+1,val+n+1);
n=unique(val+1,val+n+1)-val-1;
REP(i,1,n)cnt[i]=mp[val[i]];
Pow[0]=1;
REP(i,1,maxn-10)Pow[i]=Pow[i-1]*2%mod;
int sq=sqrt(p);
REP(i,1,sq)if(p%i==0){
d[++tot]=i;
num[i]=tot;
if(p/i!=i)d[++tot]=p/i;
}
}
int get_num(ll x){ return x*x<=p ? num[x] : num[p/x]+1;}
void work(){
dp[0][get_num(p)]=1;
REP(i,1,n)REP(j,1,tot){
int k=get_num(__gcd(val[i],d[j]));
dp[i][j]=(dp[i][j]+dp[i-1][j])%mod;
dp[i][k]=(dp[i][k]+dp[i-1][j]*(Pow[cnt[i]]-1))%mod;
}
REP(i,1,tot)REP(j,1,tot)
if(d[j]%d[i]==0)
ans[j]=(ans[j]+dp[n][i])%mod;
REP(i,1,q)write(ans[get_num(w[i])],'\n');
}
int main(){
File();
init();
work();
return 0;
}