洛谷——P3912 素数个数 Meissel-Lehmer算法 找素数快速算法

版权声明:低调地前行,越努力越幸运! https://blog.csdn.net/SSYITwin/article/details/83548197

P3912 素数个数

线性筛交了一次,一个测试点不过得90分。

#include<bits/stdc++.h> 
using namespace std;
const int MAXN=1e8+6; 
int primes[MAXN],tot=0;
bool isPrime[MAXN];
int getPrime(int n)
{
    memset(isPrime,true,sizeof(isPrime));
    for(int i=2;i<n;i++)
    {
        if(isPrime[i])
            primes[++tot]=i;
        for(int j=1;j<=tot;j++)
        {
            if(i*primes[j]>=n) break;
            isPrime[i*primes[j]]=false;
            if(i%primes[j]==0) break;//一个合数与一个素数的乘积,可以用一个更大的合数和比它小的素数求解得到 
        }
    }
    return tot;
}
int main()
{
	int n;
	cin>>n;
	cout<<getPrime(n)<<endl;
	return 0; 
}

看题解又发现更快速算法模板:

#include<bits/stdc++.h>
using namespace std;
#define N 216000
#define ll long long
int mn[N],pri[N/10],fl[N];
int tot,cnt,num,n;
int f[20005][55];
int inf=2e9;
int dp(int x,int y)
{
    if (x<=20000&&y<=50) return f[x][y];
    if (x==0||y==0) return x;
    if (1ll*pri[y]*pri[y]>=x&&x<N) return max(0,mn[x]-y);
    return dp(x,y-1)-dp(x/pri[y],y-1);
}
void pre()
{
    for (int i=2;i<N;i++)
	{
        if (!fl[i]) pri[++tot]=i;
        for (int j=1;i*pri[j]<N&&j<=tot;j++)
		{
            fl[i*pri[j]]=1;
            if (i%pri[j]==0) break;
        }
    }
    for (int i=1;i<N;i++)
        mn[i]=(cnt+=1-fl[i]);
    for (int i=1;i<=20000;i++) f[i][0]=i;
    for (int i=1;i<=20000;i++)
        for (int j=1;j<=50;j++)
            f[i][j]=f[i][j-1]-f[i/pri[j]][j-1];
}
int power(int x,int y)
{
    int s=1;
    while (y!=0)
	{
        if (y&1)
		{
            if (s>=inf/x) s=inf;
            else s=s*x;
        }
        y/=2;
        if (x>=inf/x) x=inf;
        else x=x*x;
    }
    return s;
}
int yroot(ll x,int y)
{
    int l=2,r=6666,ans=1;
    while (l<=r)
	{
        int mid=(l+r)/2;
        if (power(mid,y)<=x) ans=mid,l=mid+1;
        else r=mid-1;
    }
    return ans;
}
int judge(int m)
{
    if (m<N) return mn[m]-1;
    int y=yroot(m,3),n=mn[y];
    int ans=dp(m,n)+n-1;
    for (n++;pri[n]*pri[n]<=m;n++)
        ans-=mn[m/pri[n]]-mn[pri[n]]+1;
    return ans;
}
int main()
{
    pre();
    scanf("%d",&n);
    printf("%d\n",judge(n));
}

猜你喜欢

转载自blog.csdn.net/SSYITwin/article/details/83548197