码迷,mamicode.com
首页 > 其他好文 > 详细

欧拉筛

时间:2018-07-27 18:09:49      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:题解   长度   false   pre   lse   mat   sizeof   \n   例题   

欧拉筛可以\(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

题目传送门

待填坑。

欧拉筛

标签:题解   长度   false   pre   lse   mat   sizeof   \n   例题   

原文地址:https://www.cnblogs.com/cute-hzy/p/9378926.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!