1、题目链接:http://codeforces.com/contest/385/problem/C
2、昨天A、B两题都1Y了,剩下一个半小时就在发呆。。。要是不能突破第三题我就只能永远在DIV2混了。。。
3、刚开始觉得困难是因为L,R最多达到2*10^9,觉得筛法求素数的话数组开不了那么大,后来我发现我SB了,因为x最多10的7次方,素数总不可能超过x的最大值吧?等我反应过来的时候,比赛已经快结束了。。。
4、学会了计算空间的方法,以前看到256MB,512MB之类的都没什么概念,导致了10000000的数组都不敢开。。。没问题的,尽情开吧,本题最多可开60000000!
5、还有一个犯SB的地方就是——面对一个从小到大排好序的数组,居然挨个查找!充分体现了我的蒟蒻本质。。。应该二分查找。。。
6、我的思路也不对,刚开始是每读入一个数把它的因子都分解出来,加到f上,其实这样重复算了很多,而且算了很多不必要的数(比如合数),正确方法是用类似计数排序的方法把那些数装进数组num中,然后用类似筛法求素数的方法统计出每个因子有多少个数符合。。。“知道素数后判断是否是某数的因子”总比“知道某数后找出它有哪些因子”要容易许多。。。
7、本题是道好题啊~以后有比赛就参加吧,时间赶不上就参加virtual contest。比赛是最能发现问题的。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,num[10000010]={0},prime[670000],vis[10000010]={0},sum[670000]={0},f[670000]={0};
void sieve(int n){
int m=(int)sqrt(n+0.5);
memset(vis,0,sizeof(vis));
for(int i=2;i<=m;i++)
for(int j=i*i;j<=n;j+=i) vis[j]=1;
}
int gen_primes(int n){
sieve(n);
int c=0;
for(int i=2;i<=n;i++) if(!vis[i])
prime[c++]=i;
return c;
}
int main(){
int temp,N,m,L,R,max=0;
scanf("%d",&N);
for(int i=0;i<N;i++){
scanf("%d",&temp);
if(temp>max) max=temp;
num[temp]++;
}
int cnt=gen_primes(10000000);
for(int i=0;i<cnt;i++){
for(int j=prime[i];j<=max;j+=prime[i]){
f[i]+=num[j];
}
if(i==0) sum[0]=f[0];
else sum[i]=sum[i-1]+f[i];
}
scanf("%d",&m);
int jL,jR;
for(int i=0;i<m;i++){
scanf("%d%d",&L,&R);
jL=lower_bound(prime,prime+cnt,L)-prime;
jR=upper_bound(prime,prime+cnt,R)-prime-1;
printf("%d\n",jL>=1?sum[jR]-sum[jL-1]:sum[jR]);
}
return 0;
}