欧拉筛
Posted cute-hzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了欧拉筛相关的知识,希望对你有一定的参考价值。
欧拉筛可以(O(n))筛素数,其本质是拿每个合数的最小质因子把这个合数筛掉。
void prime(int m) {
memset(flag, 1, sizeof flag);
cnt = 0;
for(int i=2; i<=m; i++) {
if(flag[i]) pr[++ cnt] = i;
for(int j=1; j<=cnt && i * pr[j] <= m; j++) {
flag[i * pr[j]] = 0;
if(i % pr[j] == 0) break ;
}
}
}
例题1
题意
给定一个长度为(n)((n)<=(10^5))的序列(a) ((a_i <= 10^6)),求最长的满足(prod_{i=l}^{r} a_i = lcm(a_l, a_{l+1}, ldots, a_{r-1}, a_r))的子段长度.
题解
欧拉筛线性筛出每个数的最小质因子,(x)的最小质因子在(pr)中的下标记为(f(x)),即(x)的最小质因子为(pr_f(x))。
然后从(1)到(n)开始,记录右端点(r),尝试把(a_r)质因数分解加进去,直到加不进去,更新答案,把左端点向右移动一位。由于左右端点始终单调递增,复杂度(O(n))。总的复杂度应该是预处理和求解:(O(m+n log m)),m表示(a_i)的上限(10^6)。因为质因数分解需要log的复杂度,每次除去最小质因子,直到(1)。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 100010;
const int MAXA = 1000010;
int n, a[MAXN], f[MAXA];
bool flag[MAXA];
int pr[MAXA], k[MAXA], cnt;
void prime(int m) {
memset(flag, 1, sizeof flag);
cnt = 0;
for(int i=2; i<=m; i++) {
if(flag[i]) pr[++ cnt] = i, f[i] = cnt;
for(int j=1; j<=cnt && i * pr[j] <= m; j++) {
flag[i * pr[j]] = 0;
f[i * pr[j]] = j;
if(i % pr[j] == 0) break ;
}
}
}
bool valid(int x) {
while(x > 1) {
if(k[ f[x] ]) return false;
x /= pr[f[x]];
}
return true;
}
void add(int x, int v) {
while(x > 1) {
k[ f[x] ] += v;
x /= pr[f[x]];
}
}
int main() {
prime(1e6);
int T; scanf("%d", &T);
for(int Case = 1; Case <= T; ++ Case) {
int ans = -1;
scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%d", &a[i]);
int r = 0;
for(int i=1; i<=n; i++) {
while(r < n && valid(a[r + 1])) add(a[++ r], 1);
ans = max(ans, r - i + 1);
add(a[i], -1);
}
if(ans < 2) ans = -1;
printf("Case %d: %d
", ans);
}
return 0;
}
例题2:[51 Nod] 1643
待填坑。
以上是关于欧拉筛的主要内容,如果未能解决你的问题,请参考以下文章