习题:区间素数个数(min25)



题目:

求区间[1~n]的素数个数。

数据范围

n<=1e11

思路

 

min25

 

对于这道题而言,我们将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;
}


posted @ 2019-09-19 13:44  loney_s  阅读(1693)  评论(0)    收藏  举报