Codeforces 691F. Couple Cover (暴力)

来源:互联网 发布:js数组赋值 编辑:程序博客网 时间:2024/05/22 03:36

题目链接

简单题意

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

思路

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

ni=1n1i=nlog(n)

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

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

代码

#include <bits/stdc++.h>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]);    }}
0 0
原创粉丝点击