C++的数论相关算法

news2024/12/27 12:46:13

        数论是数学的一个分支,主要研究整数的性质和关系。在计算机科学中,数论算法对于密码学、优化问题和算法分析等方面都具有重要作用。C++作为一种高效的编程语言,非常适合用来实现这些算法。下面我们将介绍几个C++中的数论相关算法,包括质数的判定、求质数(埃氏筛法、欧拉筛法)、求解互质问题、中国剩余定理以及求解线性同余方程。        

一、质数的判定

        质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的数。判定一个数是否为质数,通常使用试除法,即依次检查从2到该数的平方根之间是否有因数。示例代码如下。

#include <iostream>
#include <cmath>

bool isPrime(int n) {
    if (n <= 1) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    
    for (int i = 3; i <= std::sqrt(n); i += 2) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

int main() {
    int num = 17;
    if (isPrime(num)) {
        std::cout << num << " 是素数." << std::endl;
    } else {
        std::cout << num << " 不是素数." << std::endl;
    }
    return 0;
}

        输出结果如下图所示。

 

 二、求质数(埃氏筛法)

        埃拉托斯特尼筛法(Sieve of Eratosthenes)是一种简单有效的求质数的方法。基本思想是从2开始,将每个质数的各个倍数都标记为合数,直到筛到给定范围的最大数。示例代码如下。

#include <iostream>
#include <vector>

void sieveOfEratosthenes(int n) {
    std::vector<bool> isPrime(n + 1, true);
    isPrime[0] = isPrime[1] = false;
    
    for (int p = 2; p * p <= n; ++p) {
        if (isPrime[p] == true) {
            for (int i = p * p; i <= n; i += p) {
                isPrime[i] = false;
            }
        }
    }
    
    for (int p = 2; p <= n; ++p) {
        if (isPrime[p]) {
            std::cout << p << " ";
        }
    }
    std::cout << std::endl;
}

int main() {
    int n = 30;
    std::cout << "素数小于或等于 " << n << " 的是: ";
    sieveOfEratosthenes(n);
    return 0;
}

         输出结果如下图所示。

 三、求解互质问题

        如果两个整数的最大公约数为1,则称这两个整数互质。可以使用欧几里得算法(辗转相除法)来求解两个数的最大公约数,从而判断它们是否互质。示例代码如下。

#include <iostream>

int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

bool areCoprime(int a, int b) {
    return gcd(a, b) == 1;
}

int main() {
    int num1 = 28;
    int num2 = 45;
    if (areCoprime(num1, num2)) {
        std::cout << num1 << " and " << num2 << " 是互质的." << std::endl;
    } else {
        std::cout << num1 << " and " << num2 << " 不是互质的." << std::endl;
    }
    return 0;
}

        输出结果如下图所示。

 四、中国剩余定理

        中国剩余定理是数论中的一个重要定理,用于解决一组同余方程。其目标是找到一个数,使得它除以给定的若干个数后余数分别为指定的值。示例代码如下。

#include <iostream>
#include <vector>

using namespace std;

// 扩展欧几里得算法求解ax + by = gcd(a, b)的x和y
void extendedGcd(int a, int b, int &x, int &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return;
    }
    int x1, y1;
    extendedGcd(b, a % b, x1, y1);
    x = y1;
    y = x1 - (a / b) * y1;
}

// 中国剩余定理求解
int chineseRemainderTheorem(vector<int> remainders, vector<int> moduli) {
    int product = 1;
    for (int mod : moduli) {
        product *= mod;
    }

    int result = 0;
    for (int i = 0; i < moduli.size(); i++) {
        int pp = product / moduli[i];
        int x, y;
        extendedGcd(pp, moduli[i], x, y);
        result = (result + remainders[i] * x * pp) % product;
    }
    
    if (result < 0) {
        result += product;
    }
    return result;
}

int main() {
    vector<int> remainders = {3, 2, 1};
    vector<int> moduli = {5, 4, 3};

    int result = chineseRemainderTheorem(remainders, moduli);
    cout << "满足中国余数定理的数是: " << result << endl;
    return 0;
}

        输出结果如下图所示。

 

 五、求解线性同余方程

        线性同余方程是数论中的一个重要概念,它的一般形式为 `ax ≡ b (mod m)`,其中 `a`、`b` 和 `m` 是已知整数,`x` 是未知整数。这个方程表示 `ax` 除以 `m` 的余数与 `b` 相等。求解线性同余方程在密码学、计算机科学和其他数学领域有广泛应用。

        线性同余方程可以通过扩展欧几里得算法(Extended Euclidean Algorithm)求解。扩展欧几里得算法不仅能够求出两个数的最大公约数,还能求出对应的一组整数 `x` 和 `y`,使得 `ax + by = gcd(a, b)` 成立。

        在求解线性同余方程时,我们首先需要判断方程是否有解。根据数论知识,当且仅当 `gcd(a, m)` 能够整除 `b` 时,方程才有解。

        一旦确定方程有解,我们可以使用扩展欧几里得算法求解出 `ax ≡ 1 (mod m)` 的一个特解 `x0`,然后通过 `x = x0 * (b / gcd(a, m)) % m` 得到原方程的一个解。由于线性同余方程的解具有周期性,因此所有解可以表示为 `x + km`(其中 `k` 是任意整数)。示例代码如下。

#include <iostream>

// 扩展欧几里得算法
void extendedGcd(int a, int b, int &x, int &y, int &gcd) {
    if (b == 0) {
        gcd = a;
        x = 1;
        y = 0;
        return;
    }
    extendedGcd(b, a % b, y, x, gcd);
    y -= (a / b) * x;
}

// 求解线性同余方程 ax ≡ b (mod m)
bool solveLinearCongruence(int a, int b, int m, int &x) {
    int x1, y1, gcd;
    extendedGcd(a, m, x1, y1, gcd);
    
    // 检查是否有解
    if (b % gcd != 0) {
        return false;
    }
    
    // 求解特解 x0
    x1 = (x1 * (b / gcd)) % m;
    
    // 由于线性同余方程的解具有周期性,所以只需要输出最小非负解
    x = (x1 + m) % m;
    return true;
}

int main() {
    int a = 3, b = 2, m = 5;
    int x;
    
    if (solveLinearCongruence(a, b, m, x)) {
        std::cout << "线性同余方程的解 " << a << "x ≡ " << b << " (mod " << m << ") is x = " << x << std::endl;
    } else {
        std::cout << "线性同余方程没有解." << std::endl;
    }
    
    return 0;
}

         输出结果如下图所示。

         这表示线性同余方程 `3x ≡ 2 (mod 5)` 的一个解是 `x = 4`。由于线性同余方程的解具有周期性,因此所有解可以表示为 `4 + 5k`(其中 `k` 是任意整数)。在实际应用中,我们通常关注最小非负解,因此在这个例子中,我们输出 `x = 4`。

六、实际应用

        1. 在分数计算、资源分配等场景中,我们经常需要求两个数的最大公约数(GCD)和最小公倍数(LCM)。算法实现:可以使用欧几里得算法(Euclidean Algorithm)来高效地求解最大公约数,而最小公倍数则可以通过两数之积除以它们的最大公约数得到。示例代码如下。

#include <iostream>

int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

int lcm(int a, int b) {
    return (a / gcd(a, b)) * b;
}

int main() {
    int num1 = 48, num2 = 18;
    std::cout << "GCD of " << num1 << " and " << num2 << " is: " << gcd(num1, num2) << std::endl;
    std::cout << "LCM of " << num1 << " and " << num2 << " is: " << lcm(num1, num2) << std::endl;
    return 0;
}

        2. 模幂运算与快速幂算法,在密码学、数据加密、数字签名等领域,模幂运算是一种常见的操作。快速幂算法能够高效地计算大数的幂取模结果。算法实现:利用二进制的思想,将幂次拆分为多个2的幂次的和,然后分别计算底数的这些幂次幂并取模,最后相乘并取模得到最终结果。示例代码如下。

#include <iostream>

// 快速幂算法,计算 (base^exp) % mod
long long fastPowerMod(long long base, long long exp, long long mod) {
    long long result = 1;
    base = base % mod;
    while (exp > 0) {
        if (exp % 2 == 1) {
            result = (result * base) % mod;
        }
        exp = exp >> 1;
        base = (base * base) % mod;
    }
    return result;
}

int main() {
    long long base = 2, exp = 10, mod = 1000000007; // 一个常见的大素数作为模数
    std::cout  << base << " 的 " << exp << " 次方模 " << mod << " 是: " 
              << fastPowerMod(base, exp, mod) << std::endl;
    return 0;
}

        通过上述示例,我们可以看到C++在数论相关算法的实现上具有广泛的应用。这些算法不仅在数学理论上有着深厚的基础,而且在实际应用中发挥着重要的作用。无论是在密码学、计算机科学还是其他领域,数论算法都是不可或缺的工具。通过学习和掌握这些算法,我们可以更加深入地理解计算机科学和数学的内在联系,并在实际问题中灵活运用这些算法来解决挑战。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1700316.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux入门到精通-第十九章-libevent(开源高性能事件通知库)

目录 参考什么是libevent应用核心实现libevent的地基event_base等待事件产生&#xff0c;循环监听event_loop退出循环监听event_base_loopexit创建事件工作流程 安装一&#xff08;源码安装&#xff0c;推荐&#xff09;现在源码配置编译安装验证安装 安装二&#xff08;可能因…

【记忆空间】 史上最详细,移动固态硬盘,西数BLACK D30拆解,测评,外观与内饰解析。第一期:外观与内饰。

【记忆空间】 史上最详细&#xff0c;移动固态硬盘&#xff0c;西数BLACK D30拆解&#xff0c;测评&#xff0c;外观与内饰解析。第一期&#xff1a;外观与内饰。 外观实拍&#xff0c;正面&#xff0c;整体黑色&#xff0c;外壳是一个塑料的材质。 外观实拍&#xff1a;侧面…

Android Studio开发之路(十四)自定义Titlebar以及设置顶部状态栏颜色

一、描述 项目需求&#xff0c;我要做一个下图这样的titlebar,包括一个返回按钮&#xff0c;一个关闭按钮&#xff0c;一个文本框。默认的titlebar按钮设计不太满足我的需求&#xff0c;于是我打算自定义一个titlebar组件&#xff0c;应用到我的每一个页面 二、titlebar组件设…

新计划,不断变更!做自己,接受不美好!猪肝移植——早读(逆天打工人爬取热门微信文章解读)

时间不等人 引言Python 代码第一篇 做自己&#xff0c;没有很好也没关系第二篇结尾 引言 新计划&#xff1a; 早上一次性发几个视频不现实 所以更改一下 待后面有比较稳定的框架再优化 每天早上更新 早到8点 晚到10点 你刚刚好上班或者上课 然后偷瞄的看两眼 学习一下 补充知…

HCIP-Datacom-ARST自选题库__BGP判断【20道题】

1.传统的BGP-4只能管理IPV4单播路由信息&#xff0c;MP-BGP为了提供对多种网络层协议的支持&#xff0c;对BGP-4进行了扩展。其中MP-BGP对IPv6单播网络的支持特性称为BGP4&#xff0c;BGP4通过Next Hop属性携带路由下一跳地址信息。 2.BGP4通过Update报文中的Next Hop属性携带…

C++之运算符重载

在C中&#xff0c;运算符重载是一种特殊的函数&#xff0c;它允许程序员重新定义或重载大部分内置运算符&#xff0c;以便它们可以用于用户自定义的数据类型。通过运算符重载&#xff0c;可以使自定义类型的使用更加直观和自然。 不是所有运算符都可以被重载&#xff1a; .&a…

聊聊变异测试

软件质量保障 所寫即所思&#xff5c;一个阿里质量人对测试的所感所悟。 1. 介绍 有句话说&#xff1a;证实容易&#xff0c;证伪难。正如测试一样&#xff0c;证明缺陷存在容易&#xff0c;但证明不存在缺陷难。而变异测试颠覆了这一原则&#xff0c;如果我们知道存在缺陷&am…

ARM+FPGA+NVIDIA AI摄像头软硬件定制

拥有资深ISP图像技术团队&#xff0c;是英伟达、地平线等合作伙伴&#xff0c;我们的团队掌握目前市面上大部分车载平台的ISP图像画质服务能力&#xff0c;能自主开发图像ISP和增强算法。我们具有多名经验丰富光学设计专家&#xff0c;掌握车载模组光学设计能力&#xff0c;资深…

数据结构——链表——模板类实现双向链表——先完成再完美——持续更

链表&#xff1a;概念&#xff0c;实现&#xff0c;《数据结构》这里实现是基于模板的 C语言基础&#xff0c;指针&#xff0c;引用。模板。《CPrimer》有些进阶用法放在语言学习的目录 LeetCode应用&#xff0c;会更新在LeetCode150&#xff0c;目前这个系列先暂停&#xff0c…

遇见问题-VMware虚拟机打开运行一段时间后卡死

1.问题原因 因为Windows自带的虚拟化软件Hyper-V与VMware存在冲突。 2.关闭Hyper-V 1.打开【控制面板】-【程序和功能】-【启用或关闭Windows功能】3.关闭HV主机服务 1.右击计算机-》管理-》服务和应用名称-》服务-》找到HV主机服务-》右击属性停止服务 -》启动类型设置为禁…

NASA数据集——阿尔法喷气式大气实验二氧化碳和甲烷数据

Alpha Jet Atmospheric eXperiment Carbon Dioxide and Methane Data 阿尔法喷气式大气实验二氧化碳和甲烷数据 简介 Alpha Jet Atmospheric eXperiment (AJAX) 是美国国家航空航天局艾姆斯研究中心与 H211, L.L.C. 公司的合作项目&#xff0c;旨在促进对加利福尼亚、内华达…

asp.net core接入prometheus2-自定义指标

前提 了解一下asp.net core接入prometheus快速入门 https://blog.csdn.net/qq_36437991/article/details/139064138 新建.net 8空web项目 安装下面三个包 <PackageReference Include"OpenTelemetry.Exporter.Prometheus.AspNetCore" Version"1.8.0-rc.1&…

【软件设计师】计算机组成原理

1、数据的表示 1.1 进制转换 整型有4种进制形式&#xff1a; 1.十进制&#xff08;D&#xff09;&#xff1a; 都是以0-9这九个数字组成&#xff0c;不能以0开头。 2.二进制&#xff08;B&#xff09;&#xff1a; 由0和1两个数字组成。 3.八进制&#xff08;O&#xff09;&am…

Java的类路径究竟是什么?

回答 问了chatgpt这个问题&#xff0c;首先类路径的定义是&#xff1a; 是指一组路径&#xff0c;这些路径告诉Java虚拟机&#xff08;JVM&#xff09;和类加载器在哪里可以找到应用程序所需的类和资源文件。说白了就是在运行java程序的时候需要先将java源代码编译成class文件…

代码随想录——从前序与中序遍历序列构造二叉树(Leetcode105)

题目链接 递归 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

nginx + confd + etcd 实现nginx动态白名单,防止请求host篡改注入攻击

众所周知&#xff0c;浏览器发送到后台请求header中携带的host是可能被修改的&#xff0c;为了防止这件事情发生&#xff0c;就很有必要给后台设置host请求白名单了&#xff0c;本次将介绍nginx如何配置&#xff0c;以及结合confd和etcd实现动态配置。 1. http/https请求的host…

flink cdc mysql整理与总结

文章目录 一、业务中常见的需要数据同步的场景CDC是什么FlinkCDC是什么CDC原理为什么是FlinkCDC业务场景flink cdc对应flink的版本 二、模拟案例1.阿里云flink sql2.开源flink sql(单机模式)flink 安装安装mysql3.flink datastream 三、总结 提示&#xff1a;以下是本篇文章正文…

MFC扩展库BCGControlBar Pro v34.1新版亮点:日历和计划表等功能升级

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v34.1已正式发布了&#xff0c;这个版本包含了对Windows 10/11字体图标的支持、功能区和…

huggingface 笔记:查看GPU占用情况

0 准备部分 0.1 创建虚拟数据 import numpy as npfrom datasets import Datasetseq_len, dataset_size 512, 512 dummy_data {"input_ids": np.random.randint(100, 30000, (dataset_size, seq_len)),"labels": np.random.randint(0, 1, (dataset_size…

PHP+Lucky+Baby母婴用品网站的设计与实现75554-计算机毕业设计项目选题推荐(附源码)

摘 要 近年来&#xff0c;随着移动互联网的快速发展&#xff0c;电子商务越来越受到网民们的欢迎&#xff0c;电子商务对国家经济的发展也起着越来越重要的作用。简单的流程、便捷可靠的支付方式、快捷畅通的物流快递、安全的信息保护都使得电子商务越来越赢得网民们的青睐。现…