线性筛交了一次,一个测试点不过得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));
}