查表可得约数个数上界为 1344,但当 N=1789 时会 RE,改成 N=17890 才 AC,为什么呢
#include <bits/stdc++.h>
const int mod = 1e9 + 7;
inline int mul(int x, int y){
return (int)(1ll * x * y % (1ll * mod));
}
inline int add(int x, int y){
return x + y >= mod ? x + y - mod : x + y;
}
inline int minus(int x, int y){
return x < y ? x - y + mod : x - y;
}
inline int Qpow(int x, int y){
int r = 1;
while(y){
if(y & 1) r = mul(r, x);
x = mul(x, x);
y >>= 1;
}
return r;
}
inline int read(){
char c = getchar();
int x = 0;
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
const int N = 17890;
int f[N], g[N], h[N], t[N], k[N];
int n, q, P, v[1000005], cntp = 0, cc[123], p[123], pw2[1000005];
int Div[N], cntd = 0;
int gcd(int x, int y){
return x % y == 0 ? y : gcd(y, x % y);
}
void dfs(int x, int y){
if(x == cntp + 1) return Div[++cntd] = y, (void)0;
int cury = y;
for(int i = 0; i <= cc[x]; ++i) dfs(x + 1, cury), cury *= p[x];
return ;
}
int find_(int x){
int l = 1, r = cntd;
while(l < r){
int mid = l + r >> 1;
if(Div[mid] == x) return mid;
if(Div[mid] < x) l = mid + 1;
else r = mid - 1;
}
return l;
}
void solve(){
scanf("%d%d%d", &n, &q, &P); int PP = P;
for(int i = 1; i <= n; ++i) v[i] = read();
for(int i = 2; i * i <= P; ++i)
if(PP % i == 0){
++cntp; p[cntp] = i;
while(PP % i == 0) PP /= i, ++cc[cntp];
}
if(PP) p[++cntp] = PP, cc[cntp] = 1;
dfs(1, 1);
std::sort(Div + 1, Div + cntd + 1);
//for(int i = 1; i <= cntd; ++i) printf("%d ", Div[i]);
//printf("\n");
for(int i = 1; i <= n; ++i) ++t[find_(gcd(v[i], P))];
//for(int i = 1; i <= cntd; ++i) printf("t[%d] = %d\n", i, t[i]);
for(int i = 1; i <= cntd; ++i)
for(int j = 1; j <= cntd; ++j)
if(Div[j] % Div[i] == 0)
h[i] += t[j];
//for(int i = 1; i <= cntd; ++i) printf("h[%d] = %d\n", i, h[i]);
pw2[0] = 1;
for(int i = 1; i <= n; ++i) pw2[i] = mul(2, pw2[i - 1]);
for(int i = 1; i <= cntd; ++i) g[i] = pw2[h[i]];
for(int i = cntd; i >= 1; --i){
f[i] = g[i];
for(int j = 1; j <= cntd; ++j)
if(Div[j] % Div[i] == 0 && i != j)
f[i] = minus(f[i], f[j]);
}
for(int i = 1; i <= cntd; ++i)
for(int j = 1; j <= cntd; ++j)
if(Div[i] % Div[j] == 0)
k[i] = add(k[i], f[j]);
for(int i = 1; i <= q; ++i) printf("%d\n", k[find_(gcd(P, read()))]);
return ;
}
int main(){
int T = 1;
while(T--) solve();
return 0;
}