小奇学数论

小奇学数论

时间限制: 1 Sec  内存限制: 128 MB

题目描述

小奇在数论课上学习了素数判定算法,但它不满⾜于此!
求小于等于n的素数个数。

输入

输⼊1个数字n。

输出

输出1个整数,表示答案。

样例输入

10

样例输出

4

提示

对于20%的数据,1≤n≤104
对于40%的数据,1≤n≤106
对于60%的数据,1≤n≤107
对于80%的数据,1≤n≤108
对于100%的数据,1≤n≤1011

题解

  一言不合粘板子,Meisell-Lehmer算法。

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<iostream>
  4 #define IL inline
  5 #define RG register
  6 using namespace std;
  7 typedef long long LL;
  8 const int N=5000005;
  9 const int M=7;
 10 const int PM=2*3*5*7*11*13*17;
 11 int p[N],pi[N];
 12 int phi[PM+1][M+1],sz[M+1];
 13 LL n;
 14 bool f[N];
 15 IL void getprime()
 16 {
 17     for(RG int i=2;i<N;i++)
 18     {
 19         if(!f[i])
 20             p[++p[0]]=i;
 21         pi[i]=p[0];
 22         for(RG int j=1;p[j]*i<N;j++)
 23         {
 24             f[p[j]*i]=1;
 25             if(i%p[j]==0)
 26                 break;
 27         }
 28     }
 29 }
 30 IL void init()
 31 {
 32     getprime();
 33     sz[0]=1;
 34     for(RG int i=0;i<=PM;i++)
 35         phi[i][0]=i;
 36     for(RG int i=1;i<=M;i++)
 37     {
 38         sz[i]=p[i]*sz[i-1];
 39         for(RG int j=1;j<=PM;j++)
 40             phi[j][i]=phi[j][i-1]-phi[j/p[i]][i-1];
 41     }
 42 }
 43 IL int sqrt2(LL x)
 44 {
 45     LL r=(LL)sqrt(x-0.1);
 46     while(r*r<=x) r++;
 47     return (int)(r-1);
 48 }
 49 IL int sqrt3(LL x)
 50 {
 51     LL r=(LL)cbrt(x-0.1);
 52     while(r*r*r<=x) r++;
 53     return (int)(r-1);
 54 }
 55 IL LL getphi(LL x,int s)
 56 {
 57     if(s==0) return x;
 58     if(s<=M) return phi[x%sz[s]][s]+(x/sz[s])*phi[sz[s]][s];
 59     if(x<=p[s]*p[s]*p[s]&&x<N)
 60     {
 61         int s2x=pi[sqrt2(x)];
 62         LL ans=pi[x]-(s2x+s-2)*(s2x-s+1)/2;
 63         for(RG int i=s+1;i<=s2x;i++)
 64             ans+=pi[x/p[i]];
 65         return ans;
 66     }
 67     return getphi(x,s-1)-getphi(x/p[s],s-1);
 68 }
 69 IL LL getpi(LL x)
 70 {
 71     if(x<N) return pi[x];
 72     LL ans=getphi(x,pi[sqrt3(3)])+pi[sqrt3(x)]-1;
 73     for(RG int i=pi[sqrt3(x)]+1,ed=pi[sqrt2(x)];i<=ed;i++)
 74         ans-=getpi(x/p[i])-i+1;
 75     return ans;
 76 }
 77 LL MeiLeh(LL x)
 78 {
 79     if(x<N) return pi[x];
 80     int a=(int)MeiLeh(sqrt2(sqrt2(x)));
 81     int b=(int)MeiLeh(sqrt2(x));
 82     int c=(int)MeiLeh(sqrt3(x));
 83     LL sum=getphi(x,a)+(LL)(b+a-2)*(b-a+1)/2;
 84     for(int i=a+1;i<=b;i++)
 85     {
 86         LL w=x/p[i];
 87         sum-=MeiLeh(w);
 88         if(i>c) continue;
 89         LL lim=MeiLeh(sqrt2(w));
 90         for(int j=i;j<=lim;j++)
 91             sum-=MeiLeh(w/p[j])-(j-1);
 92     }
 93     return sum;
 94 }
 95 int main()
 96 {
 97     init();
 98     while((scanf("%lld",&n))!=EOF)
 99         printf("%lld\n",MeiLeh(n));
100     return 0;
101 }
View Code

猜你喜欢

转载自www.cnblogs.com/Jony-English/p/12205034.html