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

大数取模 详解

大数取模详解

大数取模(Modular Arithmetic for Large Numbers)是计算机科学和数学中的常见问题,尤其是在密码学、数论和高效算法中广泛使用。由于大数超出常规数据类型的范围,无法直接存储或计算,因此需要采用特殊的算法和技巧来高效计算取模结果。


1. 取模运算的定义

取模运算是求两个数相除后的余数,表示为:
a m o d m = r a \mod m = r amodm=r
其中:

  • a a a是被除数。
  • m m m是模数。
  • r r r是余数,满足 0 ≤ r < m 0 \leq r < m 0r<m

例如:
13 m o d 5 = 3 ( 因为  13 = 5 × 2 + 3 ) 13 \mod 5 = 3 \quad (\text{因为 } 13 = 5 \times 2 + 3) 13mod5=3(因为 13=5×2+3)

对于大数 a a a,直接计算 a m o d m a \mod m amodm可能不可行,因此需要优化算法。


2. 常见场景

  1. 大整数取模

    • a a a是一个非常大的数,例如几百位甚至上千位。
    • 目标是高效计算 a m o d m a \mod m amodm
  2. 模运算性质

    • 利用模运算的性质简化计算,例如:
      ( a + b ) m o d m = [ ( a m o d m ) + ( b m o d m ) ] m o d m (a + b) \mod m = [(a \mod m) + (b \mod m)] \mod m (a+b)modm=[(amodm)+(bmodm)]modm

      ( a × b ) m o d m = [ ( a m o d m ) × ( b m o d m ) ] m o d m (a \times b) \mod m = [(a \mod m) \times (b \mod m)] \mod m (a×b)modm=[(amodm)×(bmodm)]modm

  3. 模幂运算

    • 计算 a b m o d m a^b \mod m abmodm,如快速幂算法。

3. 大数取模算法

(1) 基本取模方法

直接法(逐位取模)

通过逐位处理大数的每一位数字来计算取模结果。例如,对于 a = 12345678901234567890 a = 12345678901234567890 a=12345678901234567890,可以按位逐步计算 a m o d m a \mod m amodm

计算公式:
r = ( r × 10 + d i ) m o d m r = (r \times 10 + d_i) \mod m r=(r×10+di)modm
其中:

  • r r r是当前余数。
  • d i d_i di是数字 a a a的第 i i i位。
代码实现
public class BigNumberModulo {public static int bigMod(String num, int m) {int result = 0; // 初始余数为 0for (int i = 0; i < num.length(); i++) {int digit = num.charAt(i) - '0'; // 取当前位的数字result = (result * 10 + digit) % m; // 更新余数}return result;}public static void main(String[] args) {String num = "12345678901234567890"; // 大数作为字符串输入int m = 7;System.out.println(bigMod(num, m)); // 输出:6}
}
运行原理

对于大数 12345678901234567890 12345678901234567890 12345678901234567890和模数 m = 7 m = 7 m=7

  1. 从左到右逐位读取数字。
  2. 依次更新当前余数:
    • 初始 r = 0 r = 0 r=0
    • 第 1 位: r = ( 0 × 10 + 1 ) m o d 7 = 1 r = (0 \times 10 + 1) \mod 7 = 1 r=(0×10+1)mod7=1
    • 第 2 位: r = ( 1 × 10 + 2 ) m o d 7 = 5 r = (1 \times 10 + 2) \mod 7 = 5 r=(1×10+2)mod7=5
    • 以此类推,最终得出 r = 6 r = 6 r=6
时间复杂度
  • 时间复杂度为 O ( n ) O(n) O(n),其中 n n n是大数的位数。

(2) 模运算性质

性质 1:分配律

模运算满足以下分配律,可用于化简运算:

  • 加法:
    ( a + b ) m o d m = [ ( a m o d m ) + ( b m o d m ) ] m o d m (a + b) \mod m = [(a \mod m) + (b \mod m)] \mod m (a+b)modm=[(amodm)+(bmodm)]modm

  • 乘法:
    ( a × b ) m o d m = [ ( a m o d m ) × ( b m o d m ) ] m o d m (a \times b) \mod m = [(a \mod m) \times (b \mod m)] \mod m (a×b)modm=[(amodm)×(bmodm)]modm

  • 减法:
    ( a − b ) m o d m = [ ( a m o d m ) − ( b m o d m ) + m ] m o d m (a - b) \mod m = [(a \mod m) - (b \mod m) + m] \mod m (ab)modm=[(amodm)(bmodm)+m]modm

性质 2:幂运算结合律

对于幂运算:
( a b ) m o d m = ( ( a m o d m ) b ) m o d m (a^b) \mod m = ((a \mod m)^b) \mod m (ab)modm=((amodm)b)modm


(3) 快速幂取模

快速幂取模算法用于高效计算 a b m o d m a^b \mod m abmodm,通过指数的二进制分解减少运算量。

核心思想

利用:
a b m o d m = { ( a b / 2 m o d m ) 2 m o d m (b 为偶数) ( a ⋅ ( a b − 1 m o d m ) ) m o d m (b 为奇数) a^b \mod m = \begin{cases} (a^{b/2} \mod m)^2 \mod m & \text{(b 为偶数)} \\ (a \cdot (a^{b-1} \mod m)) \mod m & \text{(b 为奇数)} \end{cases} abmodm={(ab/2modm)2modm(a(ab1modm))modm(b 为偶数)(b 为奇数)

迭代实现
public class FastExponentiation {public static long modularExponentiation(long a, long b, long m) {long result = 1;a = a % m; // 先取模,简化后续运算while (b > 0) {if ((b & 1) == 1) { // 如果当前指数最低位为 1result = (result * a) % m;}a = (a * a) % m; // 平方底数b >>= 1; // 指数右移一位}return result;}public static void main(String[] args) {System.out.println(modularExponentiation(2, 10, 1000)); // 输出:24}
}
运行示例

计算 2 10 m o d 1000 2^{10} \mod 1000 210mod1000

  1. 初始 a = 2 , b = 10 , m = 1000 a = 2, b = 10, m = 1000 a=2,b=10,m=1000,结果 r e s u l t = 1 result = 1 result=1
  2. b = 10 b = 10 b=10(偶数),更新 a = 4 a = 4 a=4(平方), b = 5 b = 5 b=5
  3. b = 5 b = 5 b=5(奇数),结果 r e s u l t = 1 × 4 = 4 result = 1 \times 4 = 4 result=1×4=4,更新 a = 16 a = 16 a=16 b = 2 b = 2 b=2
  4. b = 2 b = 2 b=2(偶数),更新 a = 256 a = 256 a=256 b = 1 b = 1 b=1
  5. b = 1 b = 1 b=1(奇数),结果 r e s u l t = 4 × 256 m o d 1000 = 24 result = 4 \times 256 \mod 1000 = 24 result=4×256mod1000=24

最终结果为 24 24 24

时间复杂度
  • 快速幂算法的时间复杂度为 O ( log ⁡ b ) O(\log b) O(logb)

(4) 大数与模结合

在处理大数与模运算时,常将大数分解为部分,通过逐步取模或其他分治技术避免直接计算大数。

例:大数相乘取模

如果 a a a b b b都是大数,可以用以下公式分解:
( a ⋅ b ) m o d m = [ ( a m o d m ) ⋅ ( b m o d m ) ] m o d m (a \cdot b) \mod m = [(a \mod m) \cdot (b \mod m)] \mod m (ab)modm=[(amodm)(bmodm)]modm

实现
public class BigMultiplyModulo {public static long multiplyMod(long a, long b, long m) {long result = 0;a %= m;while (b > 0) {if ((b & 1) == 1) { // 如果最低位为 1result = (result + a) % m;}a = (a << 1) % m; // 左移并模b >>= 1; // 右移一位}return result;}public static void main(String[] args) {System.out.println(multiplyMod(123456789012345678L, 987654321098765432L, 1000000007)); // 示例}
}

4. 应用场景

  1. 密码学
    • RSA 加密算法中需要大量模运算。
  2. 大整数运算
    • 如大数阶乘取模、斐波那契数取模。
  3. 数论
    • 解决同余方程、逆元计算。

5. 总结

算法适用场景时间复杂度
快速幂取模幂运算、大指数取模 O ( log ⁡ b ) O(\log b) O(logb)
大数相乘取模两个大数相乘后的取模 O ( log ⁡ b ) O(\log b) O(logb)
模运算分配律多次加、减、乘结合取模 O ( 1 ) O(1) O(1)(单次)

大数取模的核心思想

  1. 化整为零
    • 大数通过逐步分解(如逐位取模或逐步幂运算)解决,避免一次性直接计算。
  2. 模运算性质
    • 充分利用模运算的分配律和结合律,将复杂运算转化为小数范围内的运算。
  3. 算法优化
    • 针对幂运算和乘法,通过快速幂、逐位乘法等算法降低计算复杂度。

总结应用

大数取模是数论和密码学中的重要工具,掌握其算法和性质可以有效解决诸如大数相乘、大指数幂计算等复杂问题,同时优化程序性能。


http://www.mrgr.cn/news/77935.html

相关文章:

  • 经典业务场景仿淘宝客户对话功能
  • 基于Redis实现的手机短信登入功能
  • C++:探索AVL树旋转的奥秘
  • 【Qt流式布局改造支持任意位置插入和删除】
  • Android中的依赖注入(DI)框架Hilt
  • Unity ShaderLab --- 实现局部透明
  • 【数据库原理】创建与维护表,DDL数据定义语言
  • Java项目实战II基于SpringBoot的教学资料管理系统(开发文档+数据库+源码)
  • 交叉熵 vs focal loss
  • 探索 Python 任务自动化的新境界:Invoke 库揭秘
  • AJAX请求返回报错NET::ERR_CERT_DATE_INVALID
  • 内网渗透横向移动1
  • Redis设计与实现 学习笔记 第二十一章 排序
  • 【Java】Linux、Mac、Windows 安装 Oracle JDK
  • Android 常用命令和工具解析之内存相关
  • 深入解析自适应控制算法及python实现
  • 深入解析自校正控制(STC)算法及python实现
  • Flink转换算子——flatMap/map/filter/keyby/reduce综合案例
  • git使用教程
  • Python学习------第十一天
  • 小白学多线程(持续更新中)
  • 数据结构 (5)栈
  • TCP socket api详解
  • Android 常用命令和工具解析之GPU相关
  • 数字信号处理(Digital Signal Procession)总结
  • 从搭建uni-app+vue3工程开始