1. 程式人生 > >歐拉篩

歐拉篩

http 嘗試 質因數分解 span void can == n) str

歐拉篩可以\(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\n", ans);
    }
    return 0;
}

例題2:[51 Nod] 1643

題目傳送門

待填坑。

歐拉篩