简单题意
给出一个序列,和一些询问,每个询问包含一个整数q,问序列中乘积不小于q的数对有多少对
思路
(代码更容易看懂)
因为q最多是3e6,所以只要统计一下序列中哪些数出现过,出现过多少次,然后用一个二重循环
ij
遍历
1−>3e6
,当
i∗j>3e6
时 break ,这样可以统计出,乘积为
i∗j
的数对个数,再做一个累加,就可以的到乘积小于等于
i∗j
的有多少个。可证这个复杂度是
n∗∑i=1n1i=nlog(n)
然后对输入查表,用总数减去乘积小于q的数量就得到答案。
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 10000100
#define MOD 1000000007
int n,m;
long long num[maxn],sum[maxn];
int main()
{
int t;
//scanf("%d",&t);
while(scanf("%d",&n) != EOF)
{
memset(num,0,sizeof(num));
memset(sum,0,sizeof(sum));
for(int i = 0; i < n; i++)
{
int x;
scanf("%d",&x);
num[x]++;
}
for(int i = 1; i <= 3e6; i++)
{
for(int j = 1; j <= 3e6; j++)
{
if((long long)i * j > (long long)3e6)
break;
if(j == i)
sum[i*j] -= num[i];
sum[i*j] += num[i] * num[j];
}
}
for(int i = 1; i <= 3e6; i++)
sum[i] += sum[i-1];
scanf("%d",&m);
while(m--)
{
int x;
scanf("%d",&x);
printf("%lld\n",(long long)(n-1)*n - sum[x-1]);
}
}
return 0;
}