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

告别费马小定理!用线性递推法在C++里高效搞定逆元(附完整代码)

告别费马小定理用线性递推法在C里高效搞定逆元附完整代码在算法竞赛和高性能计算领域模运算中的逆元计算一直是困扰开发者的痛点。无论是计算组合数还是解决数论问题传统方法往往面临效率瓶颈。想象一下当你在ACM赛场遇到需要快速计算十万级别逆元的问题时费马小定理的O(n log p)复杂度会让你与奖牌失之交臂——这正是线性递推法大显身手的时刻。1. 为什么我们需要更好的逆元算法逆元在模运算中的地位就像倒数在普通乘法运算中一样关键。它让我们能在模数下实现除法操作这在组合数学、密码学等领域不可或缺。但传统方法各有局限扩展欧几里得法每次计算独立无法利用之前结果费马小定理要求模数为质数且复杂度较高预处理法需要额外空间存储阶乘等中间结果特别是在计算组合数C(n,k) mod p时我们需要频繁调用逆元运算。当n达到1e6量级时传统方法的性能瓶颈就暴露无遗。线性递推法正是在这种需求下应运而生它能以O(n)的时间复杂度预处理所有逆元。实际测试表明当n1e6时线性递推法比费马小定理快约50倍2. 线性递推法的数学原理线性递推法的核心在于发现逆元之间的递推关系。让我们从模运算的基本性质出发设p为质数ip我们想求i的逆元inv[i]。定义t ⌊p/i⌋k p % i根据模运算定义有p i × t k两边对p取模得i × t k ≡ 0 (mod p)整理后i × t ≡ -k (mod p)两边乘以inv[i]×inv[k]t × inv[k] ≡ -inv[i] (mod p)最终得到递推公式inv[i] (p - t × inv[k] % p) % p或者用代码更直观地表示inv[i] (p - p/i * inv[p%i] % p) % p;这个公式的美妙之处在于它让我们能用更小的数的逆元来计算当前数的逆元形成链式反应。3. 完整实现与边界处理理解了数学原理后我们来看具体实现。以下是完整的C实现代码#include iostream using namespace std; typedef long long ll; const int MAXN 1e6 10; // 根据题目需求调整 ll inv[MAXN]; void precompute_inv(int n, int p) { inv[1] 1; // 初始条件 for(int i 2; i n; i) { inv[i] (p - p/i) * inv[p%i] % p; } } int main() { int n 1e6, p 1e97; // 示例参数 precompute_inv(n, p); // 验证输出前10个逆元 for(int i 1; i 10; i) { cout inv[ i ] inv[i] endl; } return 0; }关键实现细节初始化必须设置inv[1] 1这是递推的起点类型选择使用long long防止中间结果溢出负数处理公式中的(p - ...)确保结果为正模数限制要求p必须是质数且大于n常见错误处理当p不是质数时某些数可能没有逆元当i ≥ p时结果无定义数组大小不足导致越界4. 阶乘逆元的线性计算在组合数计算中我们经常需要阶乘的逆元。可以结合线性递推法进一步优化const int MOD 1e97; ll fact[MAXN], inv_fact[MAXN]; void precompute_factorial_inv(int n) { fact[0] inv_fact[0] 1; for(int i 1; i n; i) { fact[i] fact[i-1] * i % MOD; } // 先用线性递推法计算单个逆元 inv_fact[n] quick_pow(fact[n], MOD-2); // 费马小定理计算n!的逆元 // 反向递推计算阶乘逆元 for(int i n-1; i 1; --i) { inv_fact[i] inv_fact[i1] * (i1) % MOD; } }这种组合方法的时间复杂度仍然是O(n)但能同时提供阶乘和阶乘逆元极大简化组合数计算ll C(int n, int k) { if(k 0 || k n) return 0; return fact[n] * inv_fact[k] % MOD * inv_fact[n-k] % MOD; }5. 实战应用与性能对比让我们看一个实际比赛题目中的应用示例。假设题目要求计算∑C(n,i)² mod 1e97其中n≤1e6使用传统方法ll ans 0; for(int i 0; i n; i) { ll c C(n, i); // 每次用费马小定理计算 ans (ans c * c) % MOD; }时间复杂度O(n log MOD)使用预处理法precompute_factorial_inv(n); ll ans 0; for(int i 0; i n; i) { ll c fact[n] * inv_fact[i] % MOD * inv_fact[n-i] % MOD; ans (ans c * c) % MOD; }时间复杂度O(n)性能对比表方法n1e5时间n1e6时间内存使用费马小定理350ms3500msO(1)线性递推15ms150msO(n)虽然线性递推法需要额外O(n)空间但在时间敏感的场景下这种trade-off是完全值得的。6. 高级技巧与注意事项动态模数处理当模数不固定时可以这样实现vectorint precompute_inv(int n, int p) { vectorint inv(n1); inv[1] 1; for(int i 2; i n; i) { inv[i] (p - p/i) * inv[p%i] % p; } return inv; }内存优化如果只需要部分逆元可以用滚动变量代替数组int compute_single_inv(int i, int p) { if(i 1) return 1; return (p - p/i) * compute_single_inv(p%i, p) % p; }常见陷阱模数必须是质数初始条件inv[1]1不能遗漏中间结果可能溢出确保使用足够大的数据类型调试技巧// 验证逆元是否正确 assert(1LL * i * inv[i] % p 1);在实际比赛中我通常会这样组织代码#include bits/stdc.h using namespace std; const int N 1e65, MOD 1e97; int inv[N], fact[N], inv_fact[N]; void precompute() { inv[1] fact[0] inv_fact[0] 1; for(int i 2; i N; i) inv[i] MOD - MOD/i * inv[MOD%i] % MOD; for(int i 1; i N; i) fact[i] 1LL * fact[i-1] * i % MOD; inv_fact[N-1] 1; for(int i N-2; i 1; --i) inv_fact[i] 1LL * inv_fact[i1] * (i1) % MOD; } int C(int n, int k) { if(k 0 || k n) return 0; return 1LL * fact[n] * inv_fact[k] % MOD * inv_fact[n-k] % MOD; } int main() { precompute(); // 解决问题... }这种预处理方式虽然增加了约10行代码但能让后续的所有组合数计算都变成O(1)操作。在最近的区域赛中就有一道题直接使用这个模板比现场推导的选手快了近30分钟。

相关文章:

告别费马小定理!用线性递推法在C++里高效搞定逆元(附完整代码)

告别费马小定理!用线性递推法在C里高效搞定逆元(附完整代码) 在算法竞赛和高性能计算领域,模运算中的逆元计算一直是困扰开发者的痛点。无论是计算组合数还是解决数论问题,传统方法往往面临效率瓶颈。想象一下&#xf…...

Dify边缘推理吞吐量翻倍实录:从12QPS到29QPS的4层内核级调优(含Linux sysctl深度参数表)

第一章:Dify边缘推理吞吐量翻倍实录:从12QPS到29QPS的4层内核级调优(含Linux sysctl深度参数表)在某工业边缘AI网关部署Dify v0.6.10时,初始单节点HTTP推理服务(基于FastAPI vLLM 0.4.2)实测稳…...

Qt串口通信GUI卡顿?试试用QThread把QSerialPort丢到子线程里(附完整工程源码)

Qt串口通信性能优化:多线程架构设计与实践指南 在工业自动化、医疗设备控制和嵌入式系统开发中,串口通信作为最基础的设备交互方式,其稳定性和响应速度直接影响整个系统的用户体验。当开发者使用Qt框架构建这类专业应用时,一个常见…...

别再让JSON字段毁了你的业务代码:从阿里商品中台案例看领域模型与数据模型的正确分工

领域模型与数据模型的分工艺术:从阿里商品中台实践看架构设计的本质 记得三年前接手一个电商促销系统重构时,我发现前任开发者将所有营销规则都塞进了一个名为promotion_rules的JSON字段里。当需要增加"限购地区"功能时,团队直接在…...

2026年OpenClaw阿里云8分钟云端集成零基础部署及使用教程【超详细】

2026年OpenClaw阿里云8分钟云端集成零基础部署及使用教程【超详细】。如何集成OpenClaw?还在为部署OpenClaw到处找教程踩坑吗?别再瞎折腾了!OpenClaw一键部署攻略来了,无需代码、只需两步,新手小白也能轻松拥有专属AI助…...

Dify医疗问答上线前最后72小时:必须完成的4层语义一致性验证(含Jieba+UMLS双引擎比对模板)

第一章:Dify医疗问答上线前最后72小时:必须完成的4层语义一致性验证(含JiebaUMLS双引擎比对模板)在Dify医疗问答系统正式交付前的72小时内,语义一致性验证是阻断临床术语误释、规避医患沟通风险的核心防线。我们采用四…...

图像图片照片风格转换API接口介绍

前言 在日常工作生活中,我们可能会需要将图片转化风格后再使用,比如把自己拍的照片转换成铅笔画。图像风格转换可以帮我们实现此功能,还可用于开展趣味活动,或集成到美图应用中对图像进行风格转换。 图像风格转换可将原始图像转…...

告别objdump!用Python的pwntools一键生成汇编对应的hex机器码(附Mac/Linux安装避坑)

告别objdump!用Python的pwntools一键生成汇编对应的hex机器码(附Mac/Linux安装避坑) 在二进制安全研究和CTF竞赛中,快速将汇编指令转换为机器码是每个从业者的基本功。传统方法依赖gcc或nasm配合objdump工具链,不仅步骤…...

拯救者R7000用户看过来:保姆级教程,让你的非华为笔记本也能和MatePad Pro多屏协同

拯救者R7000与MatePad Pro多屏协同实战指南 作为一名长期使用联想拯救者R7000的游戏玩家兼生产力工具爱好者,我最近入手了华为MatePad Pro平板,却被一个现实问题困扰:如何让这台非华为笔记本与华为平板实现真正的多屏协同?经过两周…...

Xiaomi Cloud Tokens Extractor:解锁智能设备管理新维度的安全密钥提取工具

Xiaomi Cloud Tokens Extractor:解锁智能设备管理新维度的安全密钥提取工具 【免费下载链接】Xiaomi-cloud-tokens-extractor This tool retrieves tokens for all devices connected to Xiaomi cloud and encryption keys for BLE devices. 项目地址: https://gi…...

Java排序不止Comparator.comparing:用reversed()和thenComparing构建复杂排序规则(附完整代码示例)

Java排序不止Comparator.comparing:用reversed()和thenComparing构建复杂排序规则(附完整代码示例) 在电商订单管理后台,我们经常需要先按订单金额降序排列,金额相同的再按下单时间升序排列;在人力资源系统…...

从CAD老手到中望3D新手:快速上手的草图绘制习惯迁移与效率技巧

从CAD老手到中望3D新手:快速上手的草图绘制习惯迁移与效率技巧 作为一名有AutoCAD或SolidWorks经验的工程师,第一次打开中望3D的草图模块时,那种既熟悉又陌生的感觉可能会让你有些无所适从。图标位置不同了,命令名称变了&#xff…...

别再折腾WSL2了!Windows 10/11一键搞定Docker Desktop安装(附保姆级排错指南)

Windows开发者必备:Docker Desktop极简安装与高效排错全攻略 每次打开Docker Desktop时那个转个不停的鲸鱼图标,是不是让你血压飙升?作为常年与Windows系统打交道的开发者,我完全理解那种看着教程一步步操作却卡在WSL2配置环节的崩…...

国内业界首个AI一键生成手绘思维导图的脑图产品来!万兴科技旗下万兴脑图重磅焕新

4月18日至19日,2026世界思维导图暨快速阅读锦标赛博赞思维导图大师挑战赛在成都举办。本届赛事由世界思维导图理事会(WMMC)中国区组委会主办。WMMC由思维导图发明者托尼博赞创立,致力于在全球范围内推广思维导图教育与应用&#x…...

GD32F407 USB CDC虚拟串口调试实战:从枚举失败到稳定收发数据的避坑指南

GD32F407 USB CDC开发实战:从设备枚举到数据收发的深度排错手册 当你的GD32F407开发板通过USB线连接到电脑,却始终无法在设备管理器中出现那个期待的"USB串行设备"图标时,这种挫败感每个嵌入式开发者都深有体会。本文将以一个真实的…...

python+requests实现的接口自动化测试

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 框架详细教程前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jme…...

draw.io桌面版架构解析:基于Electron的跨平台图表编辑实现

draw.io桌面版架构解析:基于Electron的跨平台图表编辑实现 【免费下载链接】drawio-desktop Official electron build of draw.io 项目地址: https://gitcode.com/GitHub_Trending/dr/drawio-desktop draw.io桌面版是基于Electron框架构建的专业图表编辑工具…...

甲方爸爸要的PPT展示功能,我用Unity3d + Aspose.Slides搞定了(附打包避坑指南)

Unity3D与Aspose.Slides实战:高效集成PPT展示功能的完整方案 当甲方提出"在Unity项目中嵌入PPT展示"的需求时,许多开发者第一反应可能是寻找现成的插件或考虑导出为图片序列。但真正经历过项目交付的老手都知道,这两种方案要么功能…...

从零到一:三极管功放电路实战设计与关键参数剖析

1. 三极管功放电路设计基础 三极管功率放大电路是电子工程师必须掌握的核心技能之一。我第一次接触三极管功放是在大学电子设计竞赛时,当时需要驱动一个8Ω扬声器,但成品功放模块价格昂贵且参数固定,于是决定自己动手设计。三极管功放看似简单…...

从相位缠绕到高程图:InSAR干涉测量核心原理全解析

1. InSAR技术初探:从雷达回波到三维地表 第一次接触InSAR技术时,我被它神奇的能力震撼到了——居然能用卫星拍的照片算出地面的高度变化!这就像用普通相机拍两张照片,就能测量出建筑物的精确高度一样不可思议。InSAR全称是干涉合…...

STAP旁瓣干扰抑制:从原理到对抗仿真的实战解析

1. STAP技术入门:空时滤波的降噪艺术 想象一下你在嘈杂的鸡尾酒会上试图听清某个人的谈话。传统方法就像用手捂住一只耳朵(空域滤波),而STAP技术则是同时用手捂住耳朵并配合对方说话的节奏点头(空时联合滤波&#xff0…...

哔咔漫画下载器终极指南:打造个人离线漫画图书馆的简单方法

哔咔漫画下载器终极指南:打造个人离线漫画图书馆的简单方法 【免费下载链接】picacomic-downloader 哔咔漫画 picacomic pica漫画 bika漫画 PicACG 多线程下载器,带图形界面 带收藏夹,已打包exe 下载速度飞快 项目地址: https://gitcode.co…...

STC15单片机驱动LCD12864显示汉字和图片,串行接口比并行接口省多少IO口?

STC15单片机驱动LCD12864显示:串行接口如何极致节省IO资源 在嵌入式设备开发中,IO口资源常常成为制约功能扩展的瓶颈。以STC15W408AS驱动LCD12864液晶屏为例,当我们需要在小型温湿度计或仪表中实现汉字和图形显示时,串行接口相比并…...

imFile下载管理器深度解析:为什么它能成为你的全能下载解决方案?

imFile下载管理器深度解析:为什么它能成为你的全能下载解决方案? 【免费下载链接】imfile-desktop A full-featured download manager. 项目地址: https://gitcode.com/gh_mirrors/im/imfile-desktop 你是否曾经为下载大型文件而烦恼?…...

告别依赖地狱!Ubuntu 20.04/22.04 安装 ITK-SNAP 3.8.0 最全避坑指南(含libpng12终极解决方案)

医学影像处理利器:Ubuntu系统ITK-SNAP 3.8.0安装全攻略与疑难解析 在医学影像研究领域,ITK-SNAP作为一款开源的图像分割与可视化工具,凭借其强大的功能和友好的交互界面,成为众多科研工作者的首选。然而,当我们在较新…...

TRNSYS新手入门:从零开始搭建你的第一个建筑能耗模型(附Type56模块详解)

TRNSYS新手实战指南:Type56建筑能耗建模全流程解析 第一次打开TRNSYS时,面对数百个模块图标在画布上铺开,那种手足无措的感觉我至今记忆犹新。作为建筑能耗模拟领域的工业级软件,TRNSYS的强大之处恰恰在于其模块化设计——但这也成…...

3分钟完成Windows和Office激活:KMS_VL_ALL_AIO智能激活工具终极指南

3分钟完成Windows和Office激活:KMS_VL_ALL_AIO智能激活工具终极指南 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows系统频繁弹出激活提示而烦恼吗?Office文…...

别再手动调间距了!用Matlab的tiledlayout函数搞定论文级多图排版(附代码)

告别繁琐排版:用Matlab tiledlayout打造学术级多图布局 还在为论文中的多图排版焦头烂额?每次调整subplot位置都要耗费半小时?Matlab R2019b引入的tiledlayout功能彻底改变了这一局面。这个被严重低估的工具,能让你的科研图表排版…...

nanobot保姆级教程:Qwen3-4B tokenizer分词结果可视化、special token作用解析

nanobot保姆级教程:Qwen3-4B tokenizer分词结果可视化、special token作用解析 1. 引言 如果你正在使用大语言模型,尤其是像Qwen这样的开源模型,有没有好奇过模型到底是怎么“读”懂你输入的文字的?为什么有时候你输入一个词&am…...

别再只用箱线图了!用R的Raincloud Plots(云雨图)可视化你的纵向数据,附完整代码

用R语言打造科研级纵向数据可视化:云雨图全流程解析 第一次在学术会议上看到那张融合了散点、箱线和小提琴图的幻灯片时,我正被自己单调的柱状图折磨得昏昏欲睡。那张图表像有魔力般,既展示了整体分布规律,又保留了每个受试者的个…...