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;
}
posted @ 2019-08-29 13:35  danzh  阅读(101)  评论(0编辑  收藏  举报