Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2745 Accepted Submission(s): 1398
Problem Description
Easy question! Calculate how many primes between [1…n]!
Input
Each line contain one integer
n
(
1
<
=
n
<
=
1
0
11
)
n(1 <= n <= 10^{11})
n(1<=n<=1011).Process to end of file.
Output
For each case, output the number of primes in interval [1…n]
Sample Input
2
3
10
Sample Output
1
2
4
Source
2016 ACM/ICPC Asia Regional Shenyang Online
其实就是EES的第二部分的运用,设
f
(
p
)
=
1
f(p)=1
f(p)=1的多项式就可以了
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define maxx 322005
using namespace std;
int prime[321233],cnt;
int isp[maxx];
void init()
{
for(int i=2;i<maxx;i++)isp[i]=1;
for(int i=2;i<maxx;i++)
{
if(isp[i])prime[++cnt]=i;
for(int j=1;j<=cnt;j++)
{
ll x=(ll)prime[j]*i;
if(x>=maxx)break;
isp[x]=0;
if(i%prime[j]==0)break;
}
}
for(int i=2;i<maxx;i++)isp[i]+=isp[i-1];
//cout<<cnt<<endl;
}
ll w[maxx<<1],tot;
int id1[maxx],id2[maxx];
ll g[maxx<<1];
ll solve(ll x)
{
ll _s=sqrt(x*1.0);
tot=0;
for(ll i=1,last;i<=x;i=last+1)
{
ll now=x/i;
w[++tot]=now;
last=x/now;
if(now<=_s)id1[now]=tot;
else id2[last]=tot;
g[tot]=now-1;
}
//cout<<tot<<endl;
//for(int i=1;i<=tot;i++)
//cout<<i<<" "<<w[i]<<endl;
//cout<<"haha"<<endl;
for(int i=1;i<=cnt&&(ll)prime[i]*prime[i]<=x;i++)
{
for(int j=1;j<=tot&&(ll)prime[i]*prime[i]<=w[j];j++)
{
ll now=w[j]/prime[i];
int k=(now<=_s?id1[now]:id2[x/now]);
g[j]-=(g[k]-(i-1));
}
//cout<<g[1]<<endl;
}
return g[1];
}
int main()
{
ll n;
init();
//for(int i=1;i<100;i++)
//cout<<i<<" "<<isp[i]<<" " <<solve(i)<<endl;
while(scanf("%lld",&n)==1)
{
if(n<maxx)printf("%d\n",isp[n]);
else printf("%lld\n",solve(n));
}
return 0;
}