数据结构与算法-数学-基础数学算法(筛质数,最大公约数,最小公倍数,质因 ...

打印 上一主题 下一主题

主题 1523|帖子 1523|积分 4569

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一:筛质数:

1-埃氏筛法

该算法核心是从 2 开始,把每个质数的倍数标志为合数,时间复杂度约为 O(nloglogn)。
#include <iostream>

#include <vector>u

sing namespace std;

const int N = 1000010;

bool st[N];  // 标志数组,true表现是合数,false表现是质数

void get_primes(int n) {

    for (int i = 2; i <= n; i++) {

        if (!st) {

            for (int j = i + i; j <= n; j += i) {

                st[j] = true;

            }

        }

    }}

int main() {

    int n;

    cin >> n;

    get_primes(n);

    for (int i = 2; i <= n; i++) {

        if (!st) cout << i << ' ';

    }

    return 0;}

2-线性筛法:

在埃氏筛法的基础上进行进一步的优化,包管全部的合数都是被最小的质因子筛掉
#include <iostream>

#include <vector>

using namespace std;

const int N = 1000010;

int primes[N], cnt;  // primes数组存储质数,cnt记录质数个数

bool st[N];  // 标志数组,true表现是合数,false表现是质数

void get_primes(int n) {

    for (int i = 2; i <= n; i++) {

        if (!st) primes[cnt++] = i;

        for (int j = 0; primes[j] <= n / i; j++) {

            st[primes[j] * i] = true;

            if (i % primes[j] == 0) break;

        }

}

}

int main() {

    int n;

    cin >> n;

    get_primes(n);

    for (int i = 0; i < cnt; i++) {

        cout << primes << ' ';

    }

return 0;

}
二:最大公约数和最小公倍数

最小公约数:

是扩展欧几里得的基础版本,可以求出a和b的最小公约数
int gcd(int a, int b) {

return b ? gcd(b, a % b) : a;

}

int main() {

    int a, b;

    cin >> a >> b;

    cout << gcd(a, b) << endl;

return 0;

}

最小公倍数:

int lcm(int a, int b) {

return a*b/gcd(a,  b);

}

三:质因数:分解质因数,质因数的和,质因数个数

分解质因数:

一个很暴力的做法,最后得到n的全部质因数

#include <iostream>

using namespace std;

void divide(int x) {

    for (int i = 2; i <= x / i; i++) {

        if (x % i == 0) {

            int s = 0;

            while (x % i == 0) {

                x /= i;

                s++;

            }

            cout << i << ' ' << s << endl;

        }

    }

if (x > 1) cout << x << ' ' << 1 << endl;

}

int main() {

    int n;

    cin >> n;

    divide(n);

return 0;

}

约数的个数

若 N=p1^a1*p2^a2*⋯pk^ak​​,则 N 的约数个数为 (a1+1)(a2+1)⋯(ak+1)。
#include <iostream>

using namespace std;

int numofdividors(int x) {

    int res=1;

    for (int i = 2; i <= x / i; i++) {

        if (x % i == 0) {

            int s = 0;

            while (x % i == 0) {

                x /= i;

                s++;

            }

            cout << i << ' ' << s << endl;

            res=res*(s+1);

        }

    }

if (x > 1){

     cout << x << ' ' << 1 << endl;

     res*=2;

}

return res;

}

int main() {

    int n;

    cin >> n;

    cout<<divide(n);

return 0;

}

约数的和

N=p1^a1*p2^a2⋯pk^ak则 N 的
约数和为 (p1^0+p1^1+⋯+p1^a1)(p2^0+p2^1+⋯+p2^a2)⋯(pk^0+pk^1++pk^ak)。
int main() {

    int n;

    cin >> n;

    unordered_map<int, int> primes;

    while (n--) {

        int x;

        cin >> x;

        for (int i = 2; i <= x / i; i++) {

            while (x % i == 0) {

                x /= i;

                primes++;

            }

        }

        if (x > 1) primes[x]++;

    }

    LL res = 1;

    for (auto p : primes) {

        LL a = p.first, b = p.second;

        LL t = 1;

        while (b--) t = (t * a + 1) % mod;

        res = res * t % mod;

    }

    cout << res << endl;

return 0;

}

四:快速幂和乘法逆元

快速幂可以在logn级别的时间里确定n^b mod p
#include <iostream>

using namespace std;

typedef long long LL;

快速幂:

LL qmi(int a, int k, int p) {

    LL res = 1;

    while (k) {

        if (k & 1) res = res * a % p;

        a = (LL)a * a % p;

        k >>= 1;

    }

return res;

}

int main() {

    int a, k, p;

    cin >> a >> k >> p;

    cout << qmi(a, k, p) << endl;

return 0;

}

乘法逆元:

在mod p的环境下 a^-1 = a^ (p-2)
#include <iostream>

using namespace std;

typedef long long LL;


LL qmi(int a, int k, int p) {

    LL res = 1;

    while (k) {

        if (k & 1) res = res * a % p;

        a = (LL)a * a % p;

        k >>= 1;

    }

return res;

}

int main() {

    int a, p;

    cin >> a >> p;

    if (a % p == 0) cout << "impossible" << endl;

    else cout << qmi(a, p - 2, p) << endl;

return 0;

}

五:欧拉函数

欧拉函数 φ(n) 表现小于等于 n 且与 n 互质的正整数的个数。若 n=p1^a1*p2^a2*⋯pk^ak​,
则 φ(n)=n(1−1/p1)(1−1/p2)⋯(1−1/pk)。
欧拉函数模版:

求出某一个数的欧拉函数值
#include <iostream>using namespace std;

int phi(int x) {

    int res = x;

    for (int i = 2; i <= x / i; i++) {

        if (x % i == 0) {

            res = res / i * (i - 1);

            while (x % i == 0) x /= i;

        }

    }

    if (x > 1) res = res / x * (x - 1);

    return res;}

int main() {

    int n;

    cin >> n;

    cout << phi(n) << endl;

return 0;

}


线性筛法求出1~n的欧拉函数:

只有一点点的改变
#include <iostream>

#include <vector>

using namespace std;

const int N = 1000010;

int primes[N], cnt;  // primes数组存储质数,cnt记录质数个数

bool st[N];  // 标志数组,true表现是合数,false表现是质数

void get_primes(int n) {

    for (int i = 2; i <= n; i++) {

        if (!st) {

             primes[cnt++] = i;

             phi[cnt-1]=i-1;

}

        for (int j = 0; primes[j] <= n / i; j++) {

            st[primes[j] * i] = true;

            if (i % primes[j] == 0) {

                  phi[i*prime[j]]=phi*prime[j];

                  break;

}

            phi[i*prime[j]]=phi*(prime[j]-1);

        }

}

}

int main() {

    int n;

    cin >> n;

    get_primes(n);

    for (int i = 0; i < cnt; i++) {

        cout << primes << ' ';

    }

return 0;

}



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

慢吞云雾缓吐愁

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表