可以暴力预处理出每一种小于3000000的乘积有几种。询问的时候可以用总的方案减去比p小的有几种o(1)输出。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi = acos(-1.0), eps = 1e-8; void File() { freopen("D:\in.txt", "r", stdin); freopen("D:\out.txt", "w", stdout); } inline int read() { char c = getchar(); while (!isdigit(c)) c = getchar(); int x = 0; while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x; } const int maxn=1000000+10; int n,q; LL a[maxn],c[3*maxn],f[3*maxn]; void init() { for(LL i=1;i<=3000000;i++) { if(c[i]==0) continue; for(LL j=1;j<=i;j++) { if(c[j]==0) continue; if(i*j>3000000) break; if(i==j) f[i*j]=f[i*j]+c[i]*(c[j]-1); else f[i*j]=f[i*j]+2*c[i]*c[j]; } } for(int i=2;i<=3000000;i++) f[i]=f[i]+f[i-1]; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); c[a[i]]++; } init(); scanf("%d",&q); for(int i=1;i<=q;i++) { LL p; scanf("%lld",&p); printf("%lld ",(LL)n*(n-1)-f[p-1]); } return 0; }