您的位置:首页 > 其它

【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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: