数论 - 线性筛法与积性函数

首先以求1000000以内的素数为例来探讨筛法

Eratosthenes筛法(埃拉托斯特尼筛法)

时间复杂度:O(N*loglogN)

空间复杂度:O(N)

代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 1000005;

bool vis[maxn];
int prime[maxn];
int tot;

void init() {
    tot = 0;
    memset(vis, false, sizeof(vis));
    for(int i = 2; i < maxn; i ++) {
        if(!vis[i]) {
            prime[tot ++] = i;
            for(int j = i * 2; j < maxn; j += i) {
                vis[j] = true;
            }
        }
    }
}

int main() {

    init();

    for(int i = 0; i < 100; i ++) {
        cout << prime[i] << " ";
    }

    return 0;
}

Euler筛法(欧拉筛法)

每个合数只会被它最小的质因数筛去,因此时间复杂度为O(N)。

此种为线性筛法

代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 1000005;

bool vis[maxn];
int prime[maxn];
int tot;

void init() {
    tot = 0;
    memset(vis, false, sizeof(vis));
    for(int i = 2; i < maxn; i ++) {
        if(!vis[i]) prime[tot ++] = i;
        for(int j = 0; j < tot; j ++) {
            if(i * prime[j] > maxn) break;
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) break;
        }
    }
}

int main() {

    init();

    for(int i = 0; i < 100; i ++) {
        cout << prime[i] << " ";
    }

    return 0;
}

线性筛法求欧拉函数

代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 1000005;

bool vis[maxn];
int prime[maxn];
int fai[maxn];
int tot;

void init() {
    memset(vis, false, sizeof(vis));
    fai[1] = 1;
    tot = 0;
    for(int i = 2; i < maxn; i ++) {
        if(!vis[i]) {
            prime[tot ++] = i;
            fai[i] = i - 1;
        }
        for(int j = 0; j < tot; j ++) {
            if(i * prime[j] >= maxn) break;
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) {
                fai[i * prime[j]] = fai[i] * prime[j];
                break;
            }
            else {
                fai[i * prime[j]] = fai[i] * (prime[j] - 1);
            }
        }
    }
}

int main() {

    init();

    for(int i = 1; i < 100; i ++) {
        cout << fai[i] << " ";
    }

    return 0;
}

线性筛法求莫比乌斯函数

代码:

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 1000005;

bool vis[maxn];
int prime[maxn];
int mu[maxn];//莫比乌斯函数
int tot;

void init() {
    memset(vis, false, sizeof(vis));
    mu[1] = 1;
    tot = 0;
    for(int i = 2; i < maxn; i ++) {
        if(!vis[i]) {
            prime[tot ++] = i;
            mu[i] = -1;
        }
        for(int j = 0; j < tot; j ++) {
            if(i * prime[j] >= maxn) break;
            vis[i * prime[j]] = true;
            if(i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            }
            else {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}

int main() {

    init();

    for(int i = 1; i < 100; i ++) {
        cout << mu[i] << " ";
    }

    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-04 01:25:30

数论 - 线性筛法与积性函数的相关文章

读贾志鹏《线性筛法与积性函数》笔记

1.欧拉筛法在线性时间内求素数以及欧拉函数 代码: 1 procedure get; 2 var i,j,k:longint; 3 begin 4 tot:=0; 5 fillchar(check,sizeof(check),false); 6 for i:=2 to n do 7 begin 8 if not(check[i]) then 9 begin 10 inc(tot); 11 p[tot]:=i; 12 fai[i]:=i-1; 13 end; 14 for j:=1 to tot

线性筛与积性函数

线性筛 最初,线性筛只是用来筛质数罢了... void sieve(int n) { static int v[N], p[N], pr; // v[i] 表示 i 的最小质因子 // p[N] 和 pr 用来存质数表 for (int i = 2; i <= n; ++i) { if (v[i] == 0) v[i] = i, p[++pr] = i; // 没被筛,是质数 for (int j = 1; j <= pr && i*p[j] <= n; ++j) { v

积性函数筛法

积性函数筛法 很多常用的数论函数都是积性函数,而在题目中,我们常常需要线性(甚至更高)的筛法. 对于积性函数,我们可以在筛素数的基础上稍加修改,即可完成线性筛. 首先,注意到积性函数的特点: \[ f(xy)=f(x)\times f(y) \] 而可以线性筛的积性函数,需要知道以下两个式子的快速求法: \[ f(p)=?\quad f(p^k)=?\\p\in prime \] 其中, \(f(p)\) 大多是直接定义,\(f(p^k)\) 大多是递归定义. 我们来回忆一下素数筛的过程: in

常见积性函数(转自百科)

前面做hdu1452 用过积性函数这个东西...刚才遇到又不会了.所以弄一点资料提醒一下自己 在非数论的领域,积性函数指所有对于任何a,b都有性质f(ab)=f(a)f(b)的函数. 在数论中的积性函数:对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数. 若对于某积性函数 f(n),就算a, b不互质,也有f(ab)=f(a)f(b),则称它为完全积性的.[1] s(6)=s(2)*s(3)=3*4=12; s(20)=

HDU 1452 Happy 2004(因子和的积性函数)

题目链接 题意 : 给你一个X,让你求出2004的X次方的所有因子之和,然后对29取余. 思路 : 原来这就是积性函数,点这里这里这里,这里讲得很详细. 在非数论的领域,积性函数指所有对于任何a,b都有性质f(ab)=f(a)f(b)的函数. 在数论中的积性函数:对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数. 若对于某积性函数 f(n),就算a, b不互质,也有f(ab)=f(a)f(b),则称它为完全积性的. s(

常用积性函数的线性筛法整理

简单整理推导加代码,留复习用. 线性筛素数 最简单也最基础,直接看代码就好了\(--\) code: void Euler_Phi_Prime(int n) { is_prime[1] = true; for (int i = 2; i <= n; i++) { if (!is_prime[i]) prime[++cnt] = i; for (int j = 1; j <= cnt && i * prime[j] <= n; j++) { is_prime[i * pri

线性筛及其扩展-积性函数

线性筛 埃氏筛 对于每个数x,枚举其倍数,将kx筛去. 在埃氏筛过程中,每个数都会被筛掉多次,且对于每个数x,枚举其倍数的次数为\(\frac{n}{x}\) 故埃氏筛的时间复杂度为\(\sum_{i=1}^{n}\)\(\frac{n}{i}\)=n\(\sum_{i=1}^{n}\)\(\frac{1}{i}\)=\(n ln(n)\) 欧拉筛 在埃氏筛中,每个数会被筛掉多次,想要进一步下降复杂度,我们要求每个数只会被筛一次. 要想将多种筛去x的方法固定(唯一).我们就要采用一种方法-"最小

积性函数,线性筛入门 HDU - 2879

HDU - 2879HeHe 题意:He[N]为[0,N−1]范围内有多少个数满足式子x2≡x (mod N),求HeHe[N]=He[1]×……×He[N] 我是通过打表发现的he[x]=2k,k为x是质因子个数,不过这是可以通过积性函数证明的. 关于积性函数的定义: 对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时,f(ab)=f(a)f(b),在数论上就称它为积性函数.若对于某积性函数 f(n) ,就算a, b不互质,也有f(ab)=f(a)f(b),则称它为完全积性

HDU2879 HeHe 数论积性函数

题目名字有点搓,做题时没做出来,学长他们做出了,发现跟网上题解的思路没太大区别,网上所有题解的分析也都转自同一个地方,看样子这道题目不是那么好想的,没办法按照解析画了半天,计算器按了半天,理解了,自己敲出来了,觉得值得留念,打算再刷几道这样的 转自:http://blog.csdn.net/kksleric/article/details/8096914 定义:对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数.若对于某积