模运算的艺术:从基础到高阶的算法竞赛应用
在算法竞赛中,模运算(取模运算)是一个非常重要的概念,尤其在处理大数、防止溢出、以及解决与周期性相关的问题时。C++ 中的模运算使用
%运算符,但它的行为和使用场景需要特别注意。
1. 模运算的基本概念
模运算是指求一个数除以另一个数的余数。在 C++ 中,模运算使用 % 运算符。例如:
int a = 17;
int b = 5;
int result = a % b; // result = 2,因为 17 除以 5 的余数是 2
2. 模运算的性质
模运算有一些重要的性质,这些性质在算法竞赛中经常被用到:
-
结合律:

-
分配律:

-
幂运算的模:

3. 模运算的应用场景
3.1 防止整数溢出
在算法竞赛中,经常会遇到大数运算,直接计算可能会导致整数溢出。使用模运算可以有效地防止溢出。
例如,计算 (a×b)%m时,可以先对 a和 b分别取模,然后再相乘取模:
long long a = 123456789;
long long b = 987654321;
long long m = 1000000007;
long long result = (a % m) * (b % m) % m;
3.2 周期性问题的处理
模运算常用于处理周期性或循环性质的问题。例如,计算某个数在模 m 下的性质,或者判断两个数在模 m 下是否相等。(同余定理)



3.3 快速幂算法
快速幂算法(Exponentiation by Squaring)是一种高效计算大数幂模的方法。通过递归或迭代的方式,可以将时间复杂度从 O(n) 降低到 O(logn)。
long long fast_pow(long long base, long long exp, long long mod) {long long result = 1;while (exp > 0) {if (exp % 2 == 1) {result = (result * base) % mod;}base = (base * base) % mod;exp /= 2;}return result;
}
3.4 组合数学中的模运算
在组合数学中,模运算常用于计算组合数、排列数等。由于组合数可能非常大,通常会使用模运算来限制结果的大小。
例如,计算组合数 C(n,k)%m时,可以使用递推公式或预处理阶乘和逆阶乘的方法。
4. 负数的模运算
在 C++ 中,计算规则是:先按正整数求余,然后加上符号,模运算的结果符号与被除数相同。例如:
int a = -17;
int b = 5;
int result = a % b; // result = -2,因为 -17 除以 5 的余数是 -2
如果需要得到非负的余数,可以手动调整:(非常重要)
int mod(int a, int m) {return (a % m + m) % m;
}
5. 模运算的常见错误
-
除数为零:模运算的除数不能为零,否则会导致运行时错误。
-
负数模运算:需要注意负数的模运算结果可能不符合预期,需要手动调整。
-
溢出问题:即使使用了模运算,仍然需要注意中间结果的溢出问题。
6.取模操作满足以下性质
(1)加:(a+b)%m=((a%m)+(b&m))%m。如果没有限制a、b的正负,在C代码中的左右可能符号相反、大小相差m。
(2)减:(a-b)%m=((a%m)-(b&m))%m。在C代码中左右可能符号相反、大小相差m。
(3)乘:(a*b)%m=((a%m)*(b&m))%m。
(4)然而,对除法取模进行类似操作是错误的:(a/b)%m=((a%m)/(b&m))%m。
例如,(100/50)%20=2,(100%20)/(50%20)%20=0,两者不相等。
1. 加法取模:(a+b)%m=((a%m)+(b%m))%m
问题描述
如果没有限制 aa 和 bb 的正负,在 C++ 中,左右两边的结果可能符号相反、大小相差 mm。
原因分析
在 C++ 中,模运算 % 的结果符号与被除数相同。例如:
-
7%5=2
-
−7%5=−2
因此,如果 a 或 b 是负数,a%m 或 b%m 的结果可能是负数。当两个负数相加时,结果可能超出模数 m 的范围,导致最终结果符号相反或大小相差 m。
解决方法
为了保证结果非负,可以在最终结果上加上 m 再取模:
int mod_add(int a, int b, int m) {return ((a % m) + (b % m) + m) % m;
}
2. 减法取模:(a−b)%m=((a%m)−(b%m))%m
问题描述
在 C++ 中,左右两边的结果可能符号相反、大小相差 m。
原因分析
与加法类似,如果 a%m或 b%m 是负数,减法结果可能超出模数 m 的范围,导致最终结果符号相反或大小相差 m。
解决方法
为了保证结果非负,可以在最终结果上加上 m 再取模:
int mod_sub(int a, int b, int m) {return ((a % m) - (b % m) + m) % m;
}
3. 乘法取模:(a×b)%m=((a%m)×(b%m))%m
问题描述
乘法取模的性质在 C++ 中成立,但需要注意中间结果可能溢出。
原因分析
乘法取模的性质是基于模运算的结合律和分配律的,因此在 C++ 中成立。但如果 a 和 b 较大,直接计算 (a%m)×(b%m)可能会导致溢出。
解决方法
使用更大的数据类型(如 long long)来存储中间结果,或者分步计算:
int mod_mul(int a, int b, int m) {return ((long long)(a % m) * (b % m)) % m;
}
4. 除法取模:(a/b)%m≠((a%m)/(b%m))%m
问题描述
除法取模的性质在 C++ 中不成立。
原因分析
除法取模的性质不成立的原因是:
-
除法运算 a/b 的结果与模运算 a%m 和 b%m 没有直接关系。
-
模运算会丢失部分信息,导致除法结果无法正确反映。
解决方法
在模运算中,除法需要通过乘法逆元来实现。如果 mm 是质数,可以使用费马小定理计算逆元:(a/b)%m=(a×b−1)%m
其中 b−1 是 b 的模 m 逆元。
代码实现:
// 快速幂算法计算逆元
long long inv(long long b, long long m) {return fast_pow(b, m - 2, m);
}// 除法取模
int mod_div(int a, int b, int m) {return ((long long)(a % m) * inv(b, m)) % m;
}
7. 模运算的优化技巧
-
预处理:在需要多次进行模运算的情况下,可以预处理一些中间结果,减少重复计算。
-
位运算:在某些情况下,可以使用位运算来加速模运算,尤其是在模数为 2 的幂时。
8. 示例代码
以下是一个使用模运算的示例代码,计算斐波那契数列的第 n项模 m:
#include <iostream>
using namespace std;const int MOD = 1000000007;int fibonacci(int n) {if (n == 0) return 0;if (n == 1) return 1;int a = 0, b = 1, c;for (int i = 2; i <= n; ++i) {c = (a + b) % MOD;a = b;b = c;}return b;
}int main() {int n;cin >> n;cout << fibonacci(n) << endl;return 0;
}相关文章:
模运算的艺术:从基础到高阶的算法竞赛应用
在算法竞赛中,模运算(取模运算)是一个非常重要的概念,尤其在处理大数、防止溢出、以及解决与周期性相关的问题时。C 中的模运算使用 % 运算符,但它的行为和使用场景需要特别注意。 1. 模运算的基本概念 模运算是指求一…...
Java 并发编程——Java BIO NIO Socket编程
参考Java 并发编程——Java BIO NIO Socket编程 BIO:阻塞式编程模型 Socket 服务端编程Socket 客户端编程 NIO:非阻塞式编程模型 NIO 介绍Java 中 NIO 非阻塞式与前面 BIO 阻塞式的区别Java NIO类库包含以下三个核心组件ServerSocketChannel 服务端编程…...
ST电机库电流采样 三电阻单ADC
一、概述 下图是三电阻采样的电路结构 其中流过三相系统的电流I1、I2、I3遵循以下关系: 因此,为了重建流过普通三相负载的电流,在我们可以用以上公式计算的情况下,只需要对三相中的两相进行采样即可。 STM32的ADC可以很灵活的配置成同步采集两路ADC数据,…...
【网络】什么是 IHL(Internet Header Length,首部长度)TTL(Time To Live,生存时间)?
在 IPv4 数据报文中,IHL(Internet Header Length,首部长度)、TTL(Time To Live,生存时间) 和 TIL 涉及到 IP 数据包的结构和生命周期。以下是对它们的详细解释: 📌 1. IH…...
现代密码学 | 具有保密和认证功能的安全方案
1.案例背景 1.1 2023年6月,微软云电子邮件泄露 事件描述: 2023年6月,属于多家美国政府机构的微软云电子邮件账户遭到非法入侵,其中包括了多位高级政府官员的电子邮件。据报道,美国国务院的10个邮件账户中共有6万封电…...
一款基于Python的从常规文档里提取图片的简单工具开发方案
一款基于Python的从常规文档里提取图片的简单工具开发方案 1. 环境准备 安装必需库 pip install python-docx PyMuPDF openpyxl beautifulsoup4 pillow pip install pdfplumber # PDF解析备用方案 pip install tk # Python自带,无需安装工具选择 开发环…...
JetBrains(全家桶: IDEA、WebStorm、GoLand、PyCharm) 2024.3+ 2025 版免费体验方案
JetBrains(全家桶: IDEA、WebStorm、GoLand、PyCharm) 2024.3 2025 版免费体验方案 前言 JetBrains IDE 是许多开发者的主力工具,但从 2024.02 版本起,JetBrains 调整了试用政策,新用户不再享有默认的 30 天免费试用…...
Pytorch实现之BCGAN实现双生成器架构的人脸面部生成
简介 简介:通过双生成器架构与重建损失进行循环的生成训练,实现人脸面部表情合成。 论文题目:BCGAN: Facial Expression Synthesis by Bottleneck-Layered Conditional Generative Adversarial Networks (基于瓶颈分层条件生成对抗网络的面部表情合成) 会议:2021 15th…...
智慧加油站小程序数据库设计文档
智慧加油站系统 - 数据库与API设计文档 1. 数据库设计 1.1 ER模型 系统的核心实体关系如下: 用户(User) ---< 订单(Order) ---< 加油记录(RefuelRecord)| | || | vv v …...
Docker生存手册:安装到服务一本通
文章目录 一. Docker 容器介绍1.1 什么是Docker容器?1.2 为什么需要Docker容器?1.3 Docker架构1.4 Docker 相关概念1.5 Docker特点 二. Docker 安装2.1 查看Linux内核版本2.2 卸载老版本docker,避免产生影响2.3 升级yum 和配置源2.4 安装Dock…...
Linux内核传输层UDP源码分析
一、用户数据包协议(UDP) 1.UDP数据报头 UDP 提供面向消息的不可靠传输,但没有拥塞控制功能。很多协议都使用 UDP,如用于 IP 网络传输音频和视频的实时传输协议 (Real-time Transport Protocol,RTP),此类型…...
FPGA学习(二)——实现LED流水灯
FPGA学习(二)——实现LED流水灯 目录 FPGA学习(二)——实现LED流水灯一、DE2-115时钟源二、控制6个LED灯实现流水灯1、核心逻辑2、代码实现3、引脚配置4、实现效果 三、模块化代码1、分频模块2、复位暂停模块3、顶层模块 四、总结 一、DE2-115时钟源 DE2-115板子包含一个50MHz…...
E1-最远距离(stl使用)
题目描述 给定一个数组,请你找出数组中相同元素之间的最远距离。若数组中不存在相同元素,则输出 null。 输入描述 输入一个数组,数组长度不超过 10000。格式请见用例。 输出描述 输出数组中相同元素的最远距离。 用例 输入 [3, 2, 3,…...
Linux如何在设备树中表示和引用设备信息
DTS基本知识 dts 硬件的相应信息都会写在.dts为后缀的文件中,每一款硬件可以单独写一份xxxx.dts,一般在Linux源码中存在大量的dts文件,对于arm架构可以在arch/arm/boot/dts找到相应的dts,一个dts文件对应一个ARM的machie。 dtsi 值…...
Matlab 汽车振动多自由度非线性悬挂系统和参数研究
1、内容简介 略 Matlab 169-汽车振动多自由度非线性悬挂系统和参数研究 可以交流、咨询、答疑 2、内容说明 略 第二章 汽车模型建立 2.1 汽车悬架系统概述 2.1.1 悬架系统的结构和功能 2.1.2 悬架分类 2.2 四分之一车辆模型 对于车辆动力学,一般都是研究其悬…...
Maven核心包:maven-resolver-api
在阅读 nexus-pubic 开源项目过程中,使用了大量的核心组件进行轻量化集成。它的这种构建方式,在阅读过程中不得不感概,节省成本从构建项目的方式上就遥遥领先了。但是 maven核心包,依然使用前几年的aether-spi,却没有更…...
生活中的可靠性小案例11:窗户把手断裂
窗户把手又断了,之前也断过一次,使用次数并没有特别多。上方的图是正常的把手状态,断的形状如下方图所示。 这种悬臂梁结构,没有一个良好的圆角过渡,导致应力集中。窗户的开关,对应的是把手的推拉ÿ…...
[oeasy]python074_ai辅助编程_水果程序_fruits_apple_banana_加法_python之禅
074_ai辅助编程_水果程序_fruits_加法 回忆上次内容 上次直接从模块中导入变量、函数 from my_file import pi 导入my_file.pi 并作为 pi 使用 from my_file import pi as my_pi 导入变量 并 重命名 添加图片注释,不超过 140 字(可选) …...
【图论】并查集的学习和使用
目录 并查集是什么? 举个例子 组成 父亲数组: find函数: union函数: 代码实现: fa[] 初始化code: find code: 递归实现: 非递归实现: union code : 画图模拟: 路径压缩:…...
欢乐力扣:反转链表
文章目录 1、题目描述2、思路 1、题目描述 反转链表。 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 2、思路 借助cur指针和pre双指针来调整链表的前后指向。 # Definition for singly-linked list. # class ListNode: # def __i…...
1.8PageTable
页表的作用 虚拟地址空间映射:页表记录了进程的虚拟页号到物理页号的映射关系。每个进程都有自己的页表,操作系统为每个进程维护一个独立的页表。内存管理:页表用于实现虚拟内存管理,支持进程的虚拟地址空间和物理地址空间之间的…...
什么是大带宽服务器
什么是大带宽服务器? 在深入探讨大带宽之前,让我们先明确带宽的概念。带宽与我们日常所说的宽带有所不同,宽带是运营商为满足家庭或商业上网需求所提供的服务,而带宽则特指数据的传输速度,尤其是上行速度。大带宽服务…...
【TCP】三次挥手,四次挥手详解--UDP和TCP协议详解
活动发起人小虚竹 想对你说: 这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!…...
Compose 实践与探索十二 —— 附带效应
1、SideEffect Google 官方文档对 side effect 有两种翻译,简体中文翻译为附带效应,繁体中文翻译为副作用。这两个翻译我们用哪个都行,关键是如何理解它的含义。 1.1 什么是副作用 我们在日常生活中听到的副作用大多是医学领域中的&#x…...
Kubernetes 控制平面详解 —— 探秘 API Server、Controller Manager、Scheduler 与 etcd
文章目录 Kubernetes 控制平面详解 —— 探秘 API Server、Controller Manager、Scheduler 与 etcd控制平面概述API Server角色与职责工作原理 etcd角色与职责工作原理 Scheduler角色与职责工作原理 Controller Manager角色与职责工作原理 总结 Kubernetes 控制平面详解 —— 探…...
SSM基础专项复习4——Maven项目管理工具(1)
系列文章 1、SSM基础专项复习1——SSM项目整合-CSDN博客 2、SSM基础专项复习2——Spring 框架(1)-CSDN博客 3、SSM基础专项复习3——Spring框架(2)-CSDN博客 文章目录 系列文章 1. Maven 的概念 1.1. 什么是 Maven 1.2. 什…...
使用c#进行串口通信
一、串口通信协议 1.串口通信协议简介 串口通信(serial communication)是一种设备间非常常用的串行通信方式,大部分电子设备都支持,电子工程师再调试设备时也经常使用该通信方式输出调试信息。讲到某一种通信协议,离…...
Web开发-PHP应用鉴别修复AI算法流量检测PHP.INI通用过滤内置函数
知识点: 1、安全开发-原生PHP-PHP.INI安全 2、安全开发-原生PHP-全局文件&单函数 3、安全开发-原生PHP-流量检测&AI算法 一、演示案例-WEB开发-修复方案-PHP.INI配置 文章参考: https://www.yisu.com/ask/28100386.html https://blog.csdn.net/…...
蓝桥模拟+真题讲解
今天谁一篇文章哈 ! 由于本篇文章有些的题目只有图片,因此还望各位见谅。 目录 第一题 题目解析 代码原理 代码编写 填空技巧---巧用python 第二题 题目解析 编辑 填空技巧---巧用python 第三题 题目链接 题目解析 必备知识 解题技巧 …...
C语言【数据结构】:时间复杂度和空间复杂度.详解
引言 详细介绍什么是时间复杂度和空间复杂度。 前言:为什么要学习时间复杂度和空间复杂度 算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时…...
