Loading

「作业」线性筛素数

A. 【模板】线性筛素数

传送门:水滴

线性筛板子。原理请看这个

点击查看代码
#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int maxn = 1e8 + 10;

int prime[maxn];
bool isPrime[maxn];

void xxs (ll n) {
	int cnt = 0;
	memset (isPrime, 1, sizeof(isPrime));
	isPrime[1] = 0;
	for (int i = 2; i <= n; i++) {
		if (isPrime[i]) 
			prime[++cnt] = i;
		for (int j = 1; j <= cnt && i * prime[j] <= n; j++) {
			isPrime[i * prime[j]] = 0;
			if (i % prime[j] == 0)
				break;
		}
	}
}

int n, q;

int main(){
    scanf("%d%d", &n, &q);
    xxs (n);
    while (q--) {
    	int k; scanf("%d", &k);
    	printf("%d\n", prime[k]);
    } return 0;
}

B. A % B Problem

传送门:水滴

题目大意:给定正整数 l,r,求区间 [l,r] 中质数的个数。

首先写好线性筛板子。看到 l,r 想到预处理质数数的前缀和。设 ans[i] 表示第 i 个数中有多少质数。分两种情况:

  • i 个数是合数,就把 ans[i] 赋值为 ans[i - 1],没有对答案造成贡献。

  • i 个数是质数,就把 ans[i] 赋值为当前质数的个数。

最后判断一下边界情况,如果合法就输出 ans[r] - ans[l - 1] 即可。

点击查看代码
#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int maxn = 1e6 + 10;

int n, m;
int l, r;

int prime[maxn];
bool isPrime[maxn];
int ans[maxn];

inline void xxs(int n) {
	int cnt = 0;
	memset(isPrime, 1, sizeof(isPrime));
	isPrime[1] = 0;
	for (int i = 2; i <= n; i++) {
		ans[i] = ans[i - 1];
		if (isPrime[i])
			prime[++cnt] = i, ans[i] = cnt;
		for (int j = 1; j <= cnt && i * prime[j] <= n; j++) {
			isPrime[i * prime[j]] = 0;
			if (i % prime[j] == 0)
				break;
		}
	}
}

int main(){
    scanf("%d%d", &n, &m);
    xxs(m);
    while (n--) {
    	scanf("%d%d", &l, &r);
    	if (l > m || l < 1 || r > m || r < 1) 
    		printf("Crossing the line\n");
    	else 
    		printf("%d\n", ans[r] - ans[l - 1]);
    }
    return 0;
}

C. 集合

传送门:水滴

题目大意:要求我们在一个区间 [A,B] 中找出几个集合,集合中的数满足是一个大于等于 P 的质因数的个数。

先线性筛,然后用并查集将同质因数的数合并,最后查看有几个祖先即为答案。

点击查看代码
#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int maxn = 1e5 + 10;

int a, b, p;
int prime[maxn];
bool isPrime[maxn];
int fa[maxn];
int cnt;

inline int get(int x) {
    return x == fa[x] ? x : fa[x] = get(fa[x]);
}

inline void merge(int x, int y) {
    fa[get(x)] = get(y);
}

inline void xxs() {
	cnt = 0;
	memset(isPrime, 1, sizeof(isPrime));
	isPrime[1] = 0;
	for (int i = 2; i <= maxn; i++) {
		if (isPrime[i])
			prime[++cnt] = i;
		for (int j = 1; j <= cnt && i * prime[j] <= maxn; j++) {
			isPrime[i * prime[j]] = 0;
			if (i % prime[j] == 0)
				break;
		}
	}
}

int main() {
	xxs();
    scanf("%d%d%d", &a, &b, &p);
    for (int i = a; i <= b; i++) fa[i] = i;
    int pos = lower_bound(prime, prime + cnt, p) - prime;
    for (int i = pos; prime[i] <= b; i++) {
    	for (int j = 2; j * prime[i] <= b; j++) {
    		if ((j - 1) * prime[i] < a) continue;
    		merge((j - 1) * prime[i], j * prime[i]);
    	}
    }
    int ans = 0;
    for (int i = a; i <= b; i++)
    	if (fa[i] == i) ans ++;
    return printf("%d\n", ans), 0;
}
posted @ 2025-02-03 16:24  Aelt  阅读(6)  评论(0编辑  收藏  举报