Codeforces 691F. Couple Cover (暴力)

题目链接

简单题意

给出一个序列,和一些询问,每个询问包含一个整数q,问序列中乘积不小于q的数对有多少对

思路

(代码更容易看懂)
因为q最多是3e6,所以只要统计一下序列中哪些数出现过,出现过多少次,然后用一个二重循环 ij 遍历 1>3e6 ,当 ij>3e6 时 break ,这样可以统计出,乘积为 ij 的数对个数,再做一个累加,就可以的到乘积小于等于 ij 的有多少个。可证这个复杂度是

ni=1n1i=nlog(n)

然后对输入查表,用总数减去乘积小于q的数量就得到答案。

PS:也可以先读入数据, ij 只遍历到询问中最大的那个数,可能会快一点,但是要一个额外的数组来存询问。

代码

#include 

using namespace std;
typedef long long ll;
const int maxn = 3e6+10;
ll num[maxn];
ll sum[maxn];
int main(){
    ll n,m;
    scanf("%I64d", &n);
    ll ma = 0;
    for(int i = 0 ; i < n ; i++){
        scanf("%I64d",&m);
        num[m]++;
        ma = max(ma,m);
    }
    for(int i = 0 ; i <= ma ; i ++){
        for(int j = 0 ; j <= ma; j ++){
            if(1LL*i*j > 3e6) break;
            sum[i*j] += num[i] * num[j];
            if(i == j) sum[i*j] -= num[i];
        }
    }
    for(int i = 1 ; i < maxn ; i ++) sum[i] += sum[i-1];
    scanf("%I64d",&m);
    for(int i = 0 ; i < m ; i ++){
        ll tmp;
        scanf("%I64d", &tmp);
        printf("%I64d\n", n*(n-1) - sum[tmp-1]);
    }
}

你可能感兴趣的:(题解,codeforces)