CF:Problem 385C - Bear and Prime Numbers 预处理DP

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.
  3. The third query comes l = 4r = 4. As this interval has no prime numbers, then the sum equals 0.

题意:题意比赛的时候竟然没看懂!!!给出n个数,然后给出l与r,然后求出 l 到 r 中是素数且在这n个数中有多少个数可以整除l到r 中是素数的数。
思路:输入这n个数的时候统计数出现多少次(即c[x]++);然后用打表的方法求出每个素数被哪些数整除了的次数(即dp[i]+=d[j],非素数置-1);然后连加滚动数组到最后,即:
dp[i]=(dp[i]<0?0:dp[i])+dp[i-1]; 意思就是当前数等于前一个数的次数加上当前数的次数(如果当前数是非素数,则置0)。
然后输入l,r,就可以直接输出 dp[r]-dp[l-1],因为已经预处理过dp[i]了嘛!相减其实就是等于dp[l]到dp[r]之间的素数被整除的次数相加。因为非素数为0,所以相减是无影响的,非素数的次数会等于前一个最接近的素数的次数,由滚动数组状态方程可以看出。
感觉:本来刚开始的想法就是先判断出素数再一个一个判断,但是确实数太大会超时。所以只能是DP了。但是木想到暴力可以这样解决,太强暴了!!!受益匪浅啊!多上上CF决对有益处!!!而且这段时间我也想把DP想法与状态方法的求解有更大的提高,DP真是只要能想到,决对没有做不出来的,太爽了。算法的力量太强暴了!!!!!!!!!!!
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define f(i,a,n) for(i=a;i<n;i++)
#define F(i,a,n) for(i=a;i<=n;i++)
#define MM 10000002
#define MN 3005
#define INF 16843009000000
using namespace std;
typedef long long ll;
int n,i,j,a,l,r,c[MM],dp[MM];
int main()
{
    sca(n);
    f(i,0,n) sca(a),c[a]++;
    f(i,2,MM)
        if(dp[i]>=0)
        {
            dp[i]=c[i];
            for(j=i+i; j<MM; j+=i)
                dp[i]+=c[j],dp[j]=-1;
        }
    f(i,2,MM) dp[i]=(dp[i]<0?0:dp[i])+dp[i-1];
    sca(n);
    f(i,0,n)
    {
        scanf("%d%d",&l,&r);
        if(r>=MM) r=MM-2;
        l>r?puts("0"):pri(dp[r]-dp[l-1]);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值