习题:区间素数个数(min25)
题目:
求区间[1~n]的素数个数。
数据范围
n<=1e11
思路
对于这道题而言,我们将x的取值范围强行限制为质数,所以f(x)一定为积性函数
之后我们定义一个函数g(n,k)g(n,k)g(n,k)表示前n个数筛去了前k个质数之后的值,我们设第k个质数为prime[k],这里讨论两种情况
当prime[k]>sqrt(n)时
$g(n,k)=g(n,k−1)$
否则
$g_{n,i}=g_{n,i-1}-f_{prime_{i}}*g_{n/prime_i,i-1}-\sum_{j=1}^{i-1}f_{prime_j}$
即使你明白了这种筛法,对于此题,你还需要进行各种卡常。。。
代码
#include<iostream>
#include<cmath>
using namespace std;
long long n;
int len;
int lim;
int lenp;
long long a[7000000];
long long g[7000000];
inline int get_index(long long x)
{
if(x<=lim)
return x;
else
return len-n/x+1;
}
int main()
{
cin>>n;
lim=sqrt(n);
for(long long i=1;i<=n;i=a[len]+1)
{
a[++len]=n/(n/i);
g[len]=a[len]-1;
}
for(int i=2;i<=lim;++i)
{
if(g[i]!=g[i-1])
{
++lenp;
for(int j=len;a[j]>=1ll*i*i;--j)
g[j]=g[j]-g[get_index(a[j]/i)]+lenp-1;
}
}
cout<<g[len];
return 0;
}

浙公网安备 33010602011771号