(385C)codeforce

C. Bear and Prime Numbers
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Recently, the bear started studying data structures and faced the following problem.

You are given a sequence of integers x1, x2, ..., xn of length n and m queries, each of them is characterized by two integers li, ri. Let's introduce f(p) to represent the number of such indexes k, that xk is divisible by p. The answer to the query li, ri is the sum: , where S(li, ri) is a set of prime numbers from segment [li, ri] (both borders are included in the segment).

Help the bear cope with the problem.

Input

The first line contains integer n (1 ≤ n ≤ 106). The second line contains n integers x1, x2, ..., xn (2 ≤ xi ≤ 107). The numbers are not necessarily distinct.

The third line contains integer m (1 ≤ m ≤ 50000). Each of the following m lines contains a pair of space-separated integers, li and ri(2 ≤ li ≤ ri ≤ 2·109) — the numbers that characterize the current query.

Output

Print m integers — the answers to the queries on the order the queries appear in the input.

Sample test(s)
input
6
5 5 7 10 14 15
3
2 11
3 12
4 4
output
9
7
0
input
7
2 3 5 7 11 4 8
2
8 10
2 123
output
0
7
Note

Consider the first sample. Overall, the first sample has 3 queries.

  1. The first query l = 2r = 11 comes. You need to count f(2) + f(3) + f(5) + f(7) + f(11) = 2 + 1 + 4 + 2 + 0 = 9.
  2. The second query comes l = 3r = 12. You need to count f(3) + f(5) + f(7) + f(11) = 1 + 4 + 2 + 0 = 7.

  1. The third query comes l = 4r = 4. As this interval has no prime numbers, then the sum equals 0。

首先我们来说下题意,主要是f[p]代表p是l<=p<=r的素数,然后看Xi(1<=i<=n)是否可以是p的倍数,如果有f[p]++,然后求和。
这道题我的错误的解法直接模拟了,直接到re。。。。我也不知道为什么。只是按照上面的直接写,算是朴素算法吧
PS:昨天感冒,脑袋不灵光
接下来说下正确的解法,首先应该想到预处理,然后素数筛,素数筛学习了一种线性写法,一会另开一个博文在写。我先贴上一篇我借阅的代码
#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<set>
#include<algorithm>
#include<cmath>


#define ll __int64
#define MAX 10001009
using namespace std;


int prime[MAX];
ll sum[MAX];
int a[MAX];
int ss[MAX];


void get_prime()
{
    prime[0]=prime[1]=1;
    memset(prime,0,sizeof(prime));//0为素数
    for(int i = 2; i<MAX; i++)
    {
        sum[i] = sum[i-1];//保留前i个和
        if(!prime[i])
        {
            for(int j = i; j<MAX; j+=i)//加i的倍数的个数,素数的倍数存的是前i个素数被整出的个数和
            {
                sum[i]+=ss[j];
                prime[j] = 1;
            }
        }
    }
}
//2,4,6,8,10
//3, 6,9,12,
//4, 8,12,16
//5,15,20.25
//6, 12,18
int main()
{
    int n;
    int _max = 0;
    memset(sum,0,sizeof(sum));
    memset(ss,0,sizeof(ss));
    scanf("%d",&n);
    for(int i = 1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        ss[a[i]]++;
        _max = max(_max,a[i]);
    }
    // cout<<_max<<endl;
    get_prime();
    int m;
    scanf("%d",&m);
    while(m--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(x>_max&&y>_max)//区分界限
        {
            puts("0");
        }
        else
        {
            if(x>_max) x = _max;
            if(y>_max) y = _max;
//            for(int i = 2;i<=10;i++)
//            cout<<sum[i]<<endl;
            printf("%I64d\n",sum[y] - sum[x-1]);
        }
    }
    return 0;
}
我再来解释下这份代码,素数晒那里是i而不是 i*i或者i+i呢,按照我的理解是 加i的倍数的个数,素数的倍数存的是前i个素数被整出的个数和。我们遍历i的本身和倍数的时候把相应的个数相加保存。

你可能感兴趣的:((385C)codeforce)