题目大意
找第n个质数,n<=1e9
乱搞
Drin_E大爷教我的洲阁筛。
但是好像不是正统。
我们可以二分,所以只是判断质数个数的问题。
设c[i]表示第i个质数。
f[i]表示i以内质数个数。
设g(n,m)表示n以内不被c[1~m]整除的数个数。
设q=√n,那么n以内质数个数为f[q]+g(n,f[q])-1(1不是质数要减去)
显然g(n,m)=g(n,m-1)-g(n/c[m],m-1)
注意判边界m=0或1
还有玄学优化
设maxn为预处理范围
当n<=maxn时
如果f[n]<=m,只有1符合返回1
否则若f[√n]<=m,返回f[n]+1-m(除了m个质数外的质数都行)
具体见代码。
复杂度不会证。
maxn开到1e7差不多。
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=12500000+10;
ll f[maxn],c[maxn];
bool bz[maxn];
ll i,j,k,t,n,m,q,top;
ll l,r,mid;
ll g(ll n,int m){
if (!m) return n;
if (m==1) return n-n/2;
if (n<=maxn-10){
if (f[n]<=m) return 1;
if (f[(int)sqrt(n)]<=m) return f[n]+1-m;
}
return g(n,m-1)-g(n/c[m],m-1);
}
ll count(ll n){
q=floor(sqrt(n));
return f[q]+g(n,f[q])-1;
}
int main(){
fo(i,2,maxn-10){
if (!bz[i]) c[++top]=i;
fo(j,1,top){
if (i*c[j]>maxn-10) break;
bz[i*c[j]]=1;
if (i%c[j]==0) break;
}
}
f[1]=0;
fo(i,2,maxn-10) f[i]=f[i-1]+(!bz[i]);
scanf("%d",&n);
l=1;r=22801763489;
while (l<r){
mid=(l+r)/2;
if (count(mid)>=n) r=mid;else l=mid+1;
}
printf("%lld\n",l);
}