LightOJ1197 Help Hanzo 区间筛

LightOJ1197 Help Hanzo

标签

  • 区间筛法

前言

简明题意

  • 求区间质数个数(区间长度<=1e6)

思路

  • 区间[l,r]中的和数,质因子一定有一个<=sqrt( r)。因此提前筛出[1,sqrt( r)]中的质数,然后枚举这些质数的倍数就可以了。

注意事项

  • 注意在区间中移动的指针应该设成long long
  • 特判一下l=1的情况

总结

AC代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;

const int maxn = 1e5 + 10;

int mod;

bool no_prime[maxn];
int prime[maxn];
int shai(int n)
{
    int cnt = 0;
    no_prime[1] = 1;

    for (int i = 2; i <= n; i++)
    {
        if (!no_prime[i])
            prime[++cnt] = i;

        for (int j = 1; j <= cnt && prime[j] * i <= n; j++)
        {
            no_prime[prime[j] * i] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    return cnt;
}

bool no_prime1[(int)1e6 + 10];
int cal(int l, int r)
{
    memset(no_prime1, 0, sizeof no_prime1);
    int cnt = 0;
    for (int i = 1; prime[i] <= sqrt(r); i++)
    {
        for (long long j = max(l % prime[i] == 0 ? l : (l / prime[i] + 1) * prime[i], 2 * prime[i]); j <= r; j += prime[i])
            if (no_prime1[j - l] == 0)
                no_prime1[j - l] = 1, cnt++;
    }
    return r - l + 1 - cnt + (l == 1 ? -1 : 0);
}

void solve()
{
    shai(maxn - 10);

    int t;
    scanf("%d", &t);
    for (int i = 1; i <= t; i++)
    {
        int l, r;
        scanf("%d%d", &l, &r);

        printf("Case %d: %d\n", i, cal(l, r));
    }
}

int main()
{
    freopen("Testin.txt", "r", stdin);
    solve();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/danzh/p/11429219.html