NOIP 2019提高组模拟--质数(题解)

    xiaoxiao2023-11-06  166

    NOIP提高组–质数

    空间限制512MB(这个真的超大) 【题解】一看询问次数这么多足足有1e5;显然就不能用简单的每次询问都去搜一遍。所以很轻易就能想到是要用一下预处理。再看看题目注意关键词质数再看区间范围1e7,很容易就想到用筛法,毕竟一个一个区判断是不是质数复杂度真的太高了(无法接受)。再看看题目有一点两个质数的积,熟悉筛法的同学一下子就可以想到这就是埃氏筛(如果不了解的同学可以百度一下);所以我们可以开一个数组zs[]表示质数(鉴于本人英语不好就只能用万能的拼音了),f[]表示需要的数;

    #include<bits/stdc++.h> using namespace std; const int maxn=1e7+5; bool f[maxn];//满足条件的数 bool zs[maxn];//质数 int s[maxn];//求和 int idx,l,r; int main(){ memset(zs,1,sizeof(zs)); zs[1]=0; f[1]=0; for(int i=1;i<=maxn;i++){ if(zs[i]){/如果是质数 f[i]=1; for(int j=2;j*i<=maxn;j++){ if(j<=i&&zs[j]){ f[j*i]=1;//如果是两个质数相乘就满足条件 } zs[j*i]=0;//一定不是质数 } } s[i]=s[i-1]+f[i]; } scanf("%d",&idx); for(int i=1;i<=idx;i++){ scanf("%d%d",&l,&r); if(f[l]) printf("%d\n",s[r]-s[l]+1); else printf("%d\n",s[r]-s[l]); } return 0; }

    限于题目中的数据范围,其实不必每次都去跑到1e7,可是记录总的最大右端点做maxn

    #include<bits/stdc++.h> using namespace std; const int maxn=10000005; int maxx; bool f[maxn]; bool zs[maxn]; int s[maxn]; int idx,l[100005],r[100005]; int main(){ memset(zs,1,sizeof(zs)); zs[1]=0; f[1]=0; scanf("%d",&idx); for(int i=1;i<=idx;i++){ scanf("%d%d",&l[i],&r[i]); maxx=max(maxx,r[i]); } for(int i=1;i<=maxx;i++){ if(zs[i]){ f[i]=1; for(int j=2;j*i<=maxx;j++){ if(j<=i&&zs[j]){ f[j*i]=1; } zs[j*i]=0; } } s[i]=s[i-1]+f[i]; } for(int i=1;i<=idx;i++){ if(f[l[i]]) printf("%d\n",s[r[i]]-s[l[i]]+1); else printf("%d\n",s[r[i]]-s[l[i]]); } return 0; }

    用后面这个会快接近三秒;(可能是数据太良心了吧)

    最新回复(0)