《Liberoj6235. 区间素数个数》

求区间的素数个数。

可以构造一个积性函数f(i) = 1.

然后Min25筛统计质数和即可。

这里习惯性把F(x)写成了prime[i],其实应该是1.

对Min25的理解又加深了很多~

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,int> pii;
const int N = 1e6+5;
const int M = 1e6+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;

LL sum1[N],prime[N],id1[N],id2[N],g1[N],w[N];
LL n,Sqr,tot = 0,m = 0;
bool flag[N];
LL f1(LL x){return x - 1;}
LL F(LL x){return 1;}
int getid(LL x)
{
    if(x <= Sqr) return id1[x];
    else return id2[n/x];
}
void init()
{
    Sqr = sqrt(n),tot = 0,m = 0;
    for(int i = 2;i <= Sqr;++i)
    {
        if(!flag[i])
        {
            prime[++tot] = i;
            sum1[tot] = sum1[tot-1]+1;
        }
        for(int j = 1;j <= tot && prime[j]*i <= Sqr;++j)
        {
            flag[i*prime[j]] = 1;
            if(i%prime[j] == 0) break;
        }
    }
    for(LL L = 1,r;L <= n;L = r+1)
    {
        r = (n/(n/L)),w[++m] = (n/L);
        g1[m] = f1(w[m]);
        if(w[m] <= Sqr) id1[w[m]] = m;
        else id2[n/w[m]] = m;
    }
    for(int i = 1;i <= tot;++i){
        for(int j = 1;j <= m && prime[i]*prime[i] <= w[j];++j){
            g1[j] = g1[j] - F(prime[i]) * (g1[getid(w[j] / prime[i])] - sum1[i-1]);
        }
    }
}
int main()
{
    n = read();
    init();
    printf("%lld\n",g1[getid(n)]);
    system("pause");
    return 0;
}
View Code

 

posted @ 2020-09-25 13:28  levill  阅读(188)  评论(0编辑  收藏  举报