当前位置: 首页 > news >正文

数据结构与算法-数学-基础数学算法(筛质数,最大公约数,最小公倍数,质因数算法,快速幂,乘法逆元,欧拉函数)

一:筛质数:

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[i]) {

            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[i]) 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[i]) 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[i] << ' ';

    }

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[i]++;

            }

        }

        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[i]) {

             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[i]*prime[j];

                  break;

}

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

        }

}

}

int main() {

    int n;

    cin >> n;

    get_primes(n);

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

        cout << primes[i] << ' ';

    }

return 0;

}

相关文章:

  • pyTorch-迁移学习-图片数据增强-四种天气图片的多分类问题
  • 群体智能优化算法-白鲨优化算法(White Shark Optimizer,WSO,含Matlab源代码)
  • JS中的WeakMap
  • 思考 - 操作系统
  • 路由器工作在OSI模型的哪一层?
  • babel-runtime 如何缩小打包体积
  • usbip学习记录
  • 基于springboot微信小程序课堂签到及提问系统(源码+lw+部署文档+讲解),源码可白嫖!
  • 自动提取pdf公式 ➕ 输出 LaTeX
  • C++ 指针类型转换全面解析与最佳实践
  • PyTorch标注工具
  • 【C++】Chapter04<STL部分>:STL标准模板库概要
  • 【团体程序涉及天梯赛】L1~L2实战反思合集(C++)
  • Java并发编程高频面试题
  • Dubbo(41)如何排查Dubbo的服务不可用问题?
  • OpenCV阈值处理详解
  • 企业数据分析何时该放弃Excel?
  • No module named ‘keras.engine‘
  • mysql8.0.29 win64下载
  • SpringCloud的简单介绍
  • 外交部发言人就第78届世界卫生大会拒绝涉台提案发表谈话
  • 荷兰外交大臣费尔德坎普将访华
  • 杨国荣︱以经验说事:思想史研究中一种需要反思的现象
  • 家庭医生可提前5天预约三甲医院号源,上海常住人口签约率达45%,
  • 山东发布高温橙警:预计19日至21日局地可达40℃
  • “80后”南京大学天文与空间科学学院教授施勇加盟西湖大学