【51Nod 1184】第N个质数
2017-05-29 15:02
671 查看
转发出处:http://blog.csdn.net/doyouseeman/article/details/54747260
Description
第1个质数是2,第3个质数是5,给出一个数N,求第N个质数。
Solution
很明显这个要二分答案。 现在的主要问题就是求f[i]表示i里面有多少个质数。
这里可以用个非正式的洲阁筛。
设
f[i]表示i以内有多少个质数
p[i]表示第i个质数
g[i][j]表示前i个数不被p[1...j]整除的数有多少个
那么先来看看f,首先我们知道一个数i可以被i√以内的质数给筛掉,那么筛不掉的就是质数,所以有f[i]=f[i√]+g[i][f[i√]]-1,因为1不是质数。
然后p可以用线筛来解决。
g[i][j]可以从g[i][j-1]推过来,但是g[i][j-1]还包括一些是p[j]的倍数的数:p[j],2p[j],3p[j],4p[j]...ip[j]p[j],所以就要排除掉[1...ip[j]]中是p[1...j−1]倍数的,所以有g[i][j]=g[i][j−1]−g[ip[j]][j−1]
但是只有这个还不行,时间卡不过去。
我们考虑如何在根号时间内处理好。
那么很明显要优化求g的时间。
所以这里有两个优化:
1、当f[i]<=j,那么g[i][j]=1,因为j包含了组成[2…i]的所有质数,那么除了1以外,其他的数都会被整数。
2、如果不满足上面的条件,当f[i√]<=j,那么g[i][j]=f[i]+1-j,因为[1…i]的数可以由i√里所有的质数给筛掉,但是j包含了这些质数,那么只有除了这j个质数之外的质数,和1可以不被整除了。
剩下的要考虑的就是空间与时间的问题,51Nod这道题不打表还跑得挺慢的。
代码:
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #define fo(i,a,b) for(i=a;i<=b;i++) const int maxn=7500000+7; typedef long long ll; using namespace std; ll i,j,k,t,n,m,ans; ll r,mid,l; int f[maxn],p[maxn]; bool bz[maxn]; ll g(ll n,int m){ if(!m)return n; if(m==1)return n-n/2; if(n<=maxn-7){ if(f <=m)return 1; if(f[(int)sqrt(n)]<=m)return f -m+1; } return g(n,m-1)-g(n/p[m],m-1); } bool pan(ll x){ ll y=sqrt(x); return f[y]+g(x,f[y])-1>=n; } int main(){ fo(i,2,maxn-7){ if(!bz[i])p[++p[0]]=i; fo(j,1,p[0]){ t=p[j]*i; if(t>maxn-7)break; bz[t]=1;if(i%p[j]==0)break; } } fo(i,2,maxn-7)f[i]=f[i-1]+(bz[i]==0); scanf("%d",&n); l=1,r=22801763489; while(l<r){ mid=(l+r)/2; if(pan(mid))r=mid;else l=mid+1; } printf("%lld\n",l); }
相关文章推荐
- 51nod 1184 第N个质数(二分+大区间求素数模板)
- 51Nod-1184-第N个质数
- 51nod 1184 第N个质数
- 【51Nod 1184】第N个质数
- [51nod 1184]第N个质数
- ZJC-1489 L先生与质数V4 51Nod-1184 第N个素数 (大区间求素数个数模板+二分)
- 51nod 1181 质数中的质数(质数筛法)
- 51NOD 1181 质数中的质数(质数筛法)
- java求解第N个素数(质数)
- 【51nod】1106 质数检测
- 51NOD 1181 质数中的质数(质数筛法)
- 51nod_1106 质数检测
- 51Nod 1106 质数检测
- 51Nod-1106-质数检测
- 求第N个质数算法
- 51nod 1106 质数检测
- 51Nod 1181 质数中的质数(质数筛法)
- 51nod-【1106 质数检测】
- 【51Nod】1106 质数检测
- 51nod 1181 质数中的质数(质数筛法)