M - Help Hanzo LightOJ - 1197 (大区间求素数)
Posted wtsruvf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了M - Help Hanzo LightOJ - 1197 (大区间求素数)相关的知识,希望对你有一定的参考价值。
题意:
求[a,b]之间的素数的个数
数很大。。。数组开不起
所以要想到转化
因为小于等于b的合数的最小质因子 一定小于等于sqrt(b),所以只需要求出来[0,sqrt(b)]的素数 然后取倍数删去[a,b]之间的合数 就好了
那 为什么小于等于b的合数的最小质因子 一定小于等于sqrt(b)呢?
因为b是最大的, 所以只讨论b即可 我们来看b的因子 。。一定是从 [0,sqrt(b)] 和 [sqrt(b),b]这两个区间里各取一个
先来看[0,sqrt(b)] 如果在这里取得是一个合数 则这个合数可由比它小的质数组成 所以只讨论质数即可 然后求倍数。。删除[a,b]之间的合数
为什么不看 [sqrt(b),b] 因为如果取一个这个区间的数去求倍数删除[a,b]之间的合数的话 ,这个倍数一定是在 [0,sqrt(b)]这个区间的。。。
所以小于等于b的合数的最小质因子 一定小于等于sqrt(b)
代码如下:
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cmath> #define MOD 2018 #define LL long long #define ULL unsigned long long #define maxn 100009 #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_with_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int LL_INF = 0x7fffffffffffffff,INF = 0x3f3f3f3f; LL primes[maxn]; bool vis[maxn], bz[maxn]; int ans = 0; void init() { mem(vis,0); vis[1] = 1; for(int i=2; i<maxn; i++) if(!vis[i]) { primes[ans++] = i; for(LL j=(LL)i*i; j<maxn; j+=i) vis[j] = 1; } } int main() { init(); int T; int kase = 0; LL a, b; cin>> T; while(T--) { int res = 0; mem(bz,0); cin>> a >> b; // if(a <= 2) a = 2; int len = b - a; for(int i=0; i<ans && primes[i] * primes[i] < b; i++) { int j = a/primes[i]; if(j*primes[i] < a) j++; // 我们要找到第一个大于等于a的合数,因为出的时候是向下取整 所以要判断一下 if(j <= 1) j++; // 如果j == 1 则说明 a是一个质数 但我们要找合数 { bz[j*primes[i] - a] = 1; j++; } } if(a == 1) bz[0] = 1; // a == 1时要特殊讨论 因为1不是一个合数,无法由比它小的质数组成,也不是一个质数,所以在标记bz数组时 没有标记 就会多算 for(int k=0; k<=len; k++) if(!bz[k]) res++; printf("Case %d: %d ",++kase,res); } return 0; }
以上是关于M - Help Hanzo LightOJ - 1197 (大区间求素数)的主要内容,如果未能解决你的问题,请参考以下文章
Help Hanzo (LightOJ - 1197) 简单数论筛区间质数 (未完成)
LightOJ 1197 Help Hanzo(区间素数筛法)
B - Help Hanzo (LightOJ - 1197)