题意:
- 给一个区间边界值很大的区间,但是区间大小较小,求出该区间内所有质数个数。
知识补充:
- 因数枚举:分解一个数n,至于要从1 枚举到 n??√ 即可,然后把i和 n / i 当做因数加入vector
- 整数分解(把一个整数枚举出其质数基连乘的形式):从2开始枚举质数基,然后每次把该整数尽可能的被当前质数除去最大次数,这样该整数就会变小,极大减少枚举量。注意和map搭配使用,记录每一个质数的个数。
- 埃式素数筛法的复杂度是:Ologlogn看做线性也无妨。
- 求区间[a,b)内素数的个数,由于b的最大质数因子小于b√所有先把2到b√内的素数打表,再利用素数筛法,筛除[a,b)内所有的合数。
#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long int LL;
const int M = 100009,INF = 0x3fffffff;
vector<int> prime;
void get_prime(void) {
bool isprime[1000009];
memset(isprime, 0, 1000009);
for (int i = 2; i <= 1000000; i++) {
if (!isprime[i]) {
prime.push_back(i);
for (int j = i; j <= 1000000; j += i) isprime[j] = true;
}
}
}
int primes(LL a, LL b) {
bool isprime[1000009];
int ans = 0;
memset(isprime, 0 , b - a);
for (int i = 0; i < prime.size() && prime[i] < b; i++) {
int j = 0;
bool find = false;
for (LL k = a; k < b; k++, j++) if (k % prime[i] == 0) { find = true; break; }
if (!find) continue;
for (; j < b - a; j += prime[i]) { isprime[j] = true; if (j + a == prime[i]) ans++; }
}
for (int i = 0; i < b - a; i++) if (!isprime[i]) ans++;
if (a <= 1) ans -= 2 - a;
return ans;
}
int main(void) {
//problem: , address:
LL a, b;
get_prime();
while (~(scanf("%lld%lld", &a, &b))) {
cout << primes(a, b) << endl;
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-12 07:10:01