初等数论--Garner‘s 算法

news2025/5/31 18:32:25

0. 介绍

主要通过混合积的表示来逐步求得同余方程的解。

对于同余方程
{ x ≡ v 0 (     m o d     m 0 ) x ≡ v 1 (     m o d     m 1 ) ⋯ x ≡ v k − 1 (     m o d     m k − 1 ) \begin{equation*} \begin{cases} x \equiv v_0 \quad (\ \bmod \ m_0)\\ x \equiv v_1 \quad (\ \bmod \ m_1)\\ \cdots\\ x \equiv v_{k-1} \quad (\ \bmod \ m_{k-1})\\ \end{cases} \end{equation*} xv0( mod m0)xv1( mod m1)xvk1( mod mk1)

满足
gcd ⁡ ( m 0 , m 1 , ⋯   , m k − 1 ) = 1 \gcd(m_0,m_1, \cdots, m_{k-1})=1 gcd(m0,m1,,mk1)=1

1. 传统构造方法

M = ∏ i = 0 k − 1 m i b i = M m i , b i × i n v i ≡ 1 (     m o d     m i ) x = ∑ i = 0 k − 1 v i × b i × i n v i M=\prod_{i=0}^{k-1} m_i\\ b_i=\frac{M}{m_i}, b_i\times inv_i \equiv 1 \quad(\ \bmod\ m_i)\\ x=\sum_{i=0}^{k-1} v_i \times b_i \times inv_i M=i=0k1mibi=miM,bi×invi1( mod mi)x=i=0k1vi×bi×invi

这样构造保证了 x x x的存在性,但是在计算时 b i b_i bi比较大。

下面是示例代码


template<typename T>
T exgcd(T a, T b, T &x, T &y)  {

    if ( b == 0) {
        x = 1;
        y = 0;
        return a;
    }

    T x_0;
    T y_0;

    T d = exgcd( b, a % b, x_0, y_0);

    x = y_0;
    y = x_0 - (a / b) * y_0;

    return d;
}

ll CRT(int cnt, ll *a, ll *b) {

    ll pia = 1;
    ll res = 0;

    for (int i = 0;i < cnt; i++) {
        pia *= a[i];
    }

    for (int i = 0;i < cnt; i++) {
        ll m = pia / a[i];

        ll inv, tmp;
        exgcd( m, a[i], inv, tmp);
        
        inv = (inv % a[i] + a[i])% a[i];

        __int128 sb = m * inv  % pia * b[i] % pia;
        sb %= pia;

        res = (res + (ll) sb ) % pia;
    }
    return res;
}


2. Garner‘s算法

由中国剩余定理,我们知道必然存在 x < ∏ i = 0 k − 1 m i x <\prod_{i=0}^{k-1} m_i x<i=0k1mi满足上面的同余方程组。

x x x的混合积表示为
x = t 0 + t 1 m 0 + ⋯ + t k − 1 ∏ i = 0 k − 2 m i x=t_0 + t_1m_0+ \cdots+t_{k-1} \prod_{i=0}^{k-2} m_i x=t0+t1m0++tk1i=0k2mi
不断对 x x x ∏ i = 0 s m i \prod_{i=0}^{s} m_i i=0smi应用带余除数法可以证明 t i t_i ti的唯一性。

代入第一同余方程得到
t 0 ≡ v 0 (     m o d     m 0 ) t_0\equiv v_0 \quad (\ \bmod \ m_0) t0v0( mod m0)
t 0 = v 0 t_0 =v_0 t0=v0, 将 x x x代入第二个方程
t 0 + t 1 m 0 ≡ v 1 (     m o d     m 1 ) t 1 m 0 ≡ v 1 − t 0 (     m o d     m 1 ) t 1 ≡ ( v 1 − t 0 ) m 0 − 1 (     m o d     m 1 ) t_0 + t_1m_0 \equiv v_1 \quad (\ \bmod \ m_1)\\ t_1m_0\equiv v_1-t_0 \quad (\ \bmod \ m_1) \\ t_1 \equiv(v_1-t_0) m_0^{-1} \quad (\ \bmod\ m_1) t0+t1m0v1( mod m1)t1m0v1t0( mod m1)t1(v1t0)m01( mod m1)
我们令 X j = ∑ s = 0 j − 1 t s ∏ a = 0 s − 1 m a X_j=\sum_{s=0}^{j-1}t_s \prod_{a=0}^{s-1} m_a Xj=s=0j1tsa=0s1ma,也就是 x x x的混合积表示中的前 j j j

项;此时求 x x x相当于,求 X k X_k Xk

在求 X j X_j Xj时,我们必然已经求得了 X j − 1 X_{j-1} Xj1

代入到第 j j j个同余方程,可以得到

X j − 1 + t j ( ∏ s = 0 j − 1 m s ) ≡ v j (     m o d     m j ) t j ( ∏ s = 0 j − 1 m s ) ≡ ( v j − X j − 1 ) (     m o d     m j ) t j ≡ ( v j − X j − 1 ) ( ∏ s = 0 j − 1 m s ) − 1 (     m o d     m j ) X_{j-1} + t_j(\prod_{s=0}^{j-1}m_s) \equiv v_j \quad (\ \bmod \ m_j)\\ t_j(\prod_{s=0}^{j-1}m_s) \equiv (v_j - X_{j-1} ) \quad (\ \bmod \ m_j)\\ t_j \equiv(v_j-X_{j-1})(\prod_{s=0}^{j-1}m_s)^{-1} \quad (\ \bmod \ m_j) Xj1+tj(s=0j1ms)vj( mod mj)tj(s=0j1ms)(vjXj1)( mod mj)tj(vjXj1)(s=0j1ms)1( mod mj)

因此我们可以递推的来求 x x x
在这里插入图片描述
在应用密码学手册中给出了算法描述。

主要的解释上面已经有了,唯一需要注意的是求 ( ∏ i = 0 j − 1 m i ) − 1 (     m o d     m j ) (\prod_{i=0}^{j-1} m_i) ^{-1} \quad(\ \bmod\ m_j) (i=0j1mi)1( mod mj)

运用了乘积的逆等于逆的乘积这一性质, 证明如下

( ∏ i = 0 j − 1 m i ) ∏ i = 0 j − 1 ( m i ) − 1 ≡ ∏ i = 0 j − 1 m i m i − 1 ≡ 1 (     m o d     m j ) (\prod_{i=0}^{j-1} m_i)\prod_{i=0}^{j-1}(m_i)^{-1} \equiv \prod_{i=0}^{j-1} m_i m_i^{-1} \equiv 1 \quad (\ \bmod\ m_j) (i=0j1mi)i=0j1(mi)1i=0j1mimi11( mod mj)

代码

#include <iostream>
#include <vector>


using ll = long long;

static constexpr int MAXN = 1e5+10;

ll a[MAXN];
ll b[MAXN];




template<typename T>
T exgcd(T a, T b, T &x, T &y)  {

    if ( b == 0) {
        x = 1;
        y = 0;
        return a;
    }

    T x_0;
    T y_0;

    T d = exgcd( b, a % b, x_0, y_0);

    x = y_0;
    y = x_0 - (a / b) * y_0;

    return d;
}


ll CRT_GARNER(int cnt, ll *m, ll *v)
{
    std::vector<ll> C(cnt, 1);

    for (int i = 1; i < cnt; i++) {
        for (int j = 0; j < i; ++j) {
            ll inv;
            ll tmp;
            exgcd(m[j], m[i], inv, tmp);

            // printf("inv of m[%d] mod m[%d]: %d\n", j, i, inv);
            while ( inv < 0)
                inv += m[i];
            C[ i ] = C[ i ] * inv % m[i];

        }
    }

    ll u = v[ 0 ];
    ll x = u;

    ll M = m[0];
    for (int i = 1;i < cnt; i++) {
        u = (v[i] - x) * C[i] % m[i];

        while (u < 0)
            u += m[ i ];

        x = x + u * M; 
        M *= m[i];
    }

    return x;
}

举个例子
{ x ≡ 2 (     m o d     3 ) x ≡ 3 (     m o d     5 ) x ≡ 2 (     m o d     7 ) \begin{equation*} \begin{cases} x \equiv 2\quad(\ \bmod \ 3)\\ x \equiv 3 \quad (\ \bmod \ 5)\\ x \equiv 2 \quad (\ \bmod \ 7) \end{cases} \end{equation*} x2( mod 3)x3( mod 5)x2( mod 7)

x x x表示为混积的形式
x = t 0 + 2 t 1 + 15 t 2 x=t_0+2t_1+15t_2 x=t0+2t1+15t2

显然 t 0 = 2 t_0=2 t0=2

代入到第二个同余方程
2 + 3 t 1 ≡ 3 (     m o d     5 ) 3 t 1 ≡ 1 (     m o d     5 ) t 1 ≡ 3 − 1 (     m o d     5 ) 2+3t_1 \equiv 3 \quad (\ \bmod \ 5)\\ 3t_1 \equiv1 \quad (\ \bmod \ 5)\\ t_1\equiv3^{-1} \quad (\ \bmod\ 5)\\ 2+3t13( mod 5)3t11( mod 5)t131( mod 5)
3 − 1 (     m o d     5 ) 3^{-1} \quad (\ \bmod \ 5) 31( mod 5)可由扩展欧几里得算法求得
3 × 2 − 1 × 5 = 1 3 − 1 (   m o d      5 ) = 2 3 \times 2 -1 \times 5=1\\ 3^{-1} \quad( \ \mod \ 5) =2 3×21×5=131( mod 5)=2
因此 t 2 = 2 t_2=2 t2=2

代入第三个同余方程

2 + 3 × 2 + 15 t 2 = 8 + 15 t 2 15 t 2 + 8 ≡ 2 (     m o d     7 ) 15 t 2 ≡ 1 (   m o d     7 ) t 2 ≡ 15 − 1 (     m o d     7 ) 2+3\times2+15t_2=8+15t_2\\ 15t_2+8 \equiv2 \quad (\ \bmod\ 7)\\ 15t_2 \equiv1 \quad ( \bmod\ 7)\\ t_2\equiv15^{-1}\quad(\ \bmod \ 7) 2+3×2+15t2=8+15t215t2+82( mod 7)15t21(mod 7)t2151( mod 7)
同样是利用扩展欧几里得求出逆元
t 2 ≡ 1 (     m o d     7 ) t_2 \equiv 1 \quad (\ \bmod \ 7) t21( mod 7)

代入到混合积形式
x = 8 + 15 = 23 x=8+ 15=23 x=8+15=23

参考

oi-wiki-crt
handbook-of-applied-crypho

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

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

相关文章

NV211NV212美光科技颗粒NV219NV220

NV211NV212美光科技颗粒NV219NV220 技术架构解析&#xff1a;从颗粒到存储系统 近期美光科技发布的NV211、NV212、NV219、NV220系列固态颗粒&#xff0c;凭借其技术突破引发行业关注。这些颗粒基于176层QLC堆叠工艺&#xff0c;单Die容量预计在2026年可达1Tb&#xff0c;相当…

SQL解析工具JSQLParser

目录 一、引言二、JSQLParser常见类2.1 Class Diagram2.2 Statement2.3 Expression2.4 Select2.5 Update2.6 Delete2.7 Insert2.8 PlainSelect2.9 SetOperationList2.10 ParenthesedSelect2.11 FromItem2.12 Table2.13 ParenthesedFromItem2.14 SelectItem2.15 BinaryExpressio…

Wave Terminal + Cpolar:SSH远程访问的跨平台实战+内网穿透配置全解析

文章目录 前言1. Wave Terminal安装2. 简单使用演示3. 连接本地Linux服务器3.1 Ubuntu系统安装ssh服务3.2 远程ssh连接Ubuntu 4. 安装内网穿透工具4.1 创建公网地址4.2 使用公网地址远程ssh连接 5. 配置固定公网地址 前言 各位开发者朋友&#xff0c;今天为您介绍一款颠覆性操…

html使用JS实现账号密码登录的简单案例

目录 案例需求 思路 错误案例及问题 修改思路 案例提供 所需要的组件 <input>标签&#xff0c;<button>标签&#xff0c;<script>标签 详情使用参考&#xff1a;HTML 教程 | 菜鸟教程 案例需求 编写一个程序&#xff0c;最多允许用户尝试登录 3 次。…

【数据集】基于ubESTARFM法的100m 地温LST数据集(澳大利亚)

目录 数据概述一、输入数据与处理二、融合算法1. ESTARFM(Enhanced STARFM)2. ubESTARFM(Unbiased ESTARFM)代码实现数据下载参考根据论文《Generating daily 100 m resolution land surface temperature estimates continentally using an unbiased spatiotemporal fusion…

51c自动驾驶~合集55

我自己的原文哦~ https://blog.51cto.com/whaosoft/13935858 #Challenger 端到端碰撞率暴增&#xff01;清华&吉利,框架&#xff1a;低成本自动生成复杂对抗性驾驶场景~ 自动驾驶系统在对抗性场景&#xff08;Adversarial Scenarios&#xff09;中的可靠性是安全落…

【前端基础】Promise 详解

文章目录 什么是 Promise&#xff1f;为什么要使用 Promise&#xff1f;创建 Promise消费 Promise (使用 Promise)1. .then(onFulfilled, onRejected)2. .catch(onRejected)3. .finally(onFinally) Promise 链 (Promise Chaining)Promise 的静态方法1. Promise.resolve(value)2…

高性能管线式HTTP请求

高性能管线式HTTP请求:原理、实现与实践 目录 高性能管线式HTTP请求:原理、实现与实践 1. HTTP管线化的原理与优势 1.1 HTTP管线化的基本概念 关键特性: 1.2 管线化的优势 1.3 管线化的挑战 2. 高性能管线式HTTP请求的实现方案 2.1 技术选型与工具 2.2 Java实现:…

【CSS】九宫格布局

CSS Grid布局&#xff08;推荐&#xff09; 实现代码&#xff1a; <!doctype html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0"…

Python用Transformer、Prophet、RNN、LSTM、SARIMAX时间序列预测分析用电量、销售、交通事故数据

原文链接&#xff1a; tecdat.cn/?p42219 在数据驱动决策的时代&#xff0c;时间序列预测作为揭示数据时序规律的核心技术&#xff0c;已成为各行业解决预测需求的关键工具。从能源消耗趋势分析到公共安全事件预测&#xff0c;不同领域的数据特征对预测模型的适应性提出了差异…

java基础(面向对象进阶高级)泛型(API一)

认识泛型 泛型就等于一个标签(比如男厕所和女厕) 泛型类 只能加字符串&#xff1a; 把别人写好的东西&#xff0c;自己封装。 泛型接口 泛型方法、泛型通配符、上下限 怎么解决下面的问题&#xff1f; API object类 toString: equals: objects类 包装类 为什么上面的Integer爆红…

学习心得(17--18)Flask表单

一. 认识表单&#xff1a;定义表单类 password2中末端的EqualTo&#xff08;password&#xff09;是将密码2与密码1进行验证&#xff0c;看是否相同 二.使用表单&#xff1a; 运行 如果遇到这个报错&#xff0c;就在该页面去添加 下面是举例&#xff1a; 这就是在前端的展示效…

微信小程序进阶第2篇__事件类型_冒泡_非冒泡

在小程序中&#xff0c; 事件分为两种类型&#xff1a; 冒泡事件&#xff0c; 当一个组件上的事件被触发后&#xff0c;该事件会向父节点传递非冒泡事件&#xff0c; 当一个组件上的事件被触发后&#xff0c; 该事件不会向父节点传递。 一 冒泡事件 tap&#xff0c; touchst…

电机控制学习笔记

文章目录 前言一、电机二、编码器三、开环控制和闭环控制总结 前言 学习了解电机控制技术的一些原理和使用的方法。 一、电机 直流有刷电机 操作简单 使用H桥驱动直流有刷电机 直流有刷电机驱动板 电压检测 电流检测以及温度检测 直流无刷电机 使用方波或者正弦波进行换向…

企业网站架构部署与优化-Nginx性能调优与深度监控

目录 #1.1Nginx性能调优 1.1.1更改进程数与连接数 1.1.2静态缓存功能设置 1.1.3设置连接超时 1.1.4日志切割 1.1.5配置网页压缩 #2.1nginx的深度监控 2.1.1GoAccess简介 2.1.2nginx vts简介 1.1Nginx性能调优 1.1.1更改进程数与连接数 &#xff08;1&#xff09;进程数 进程数…

行列式的线性性质(仅限于单一行的加法拆分)

当然可以&#xff0c;以下是经过排版优化后的内容&#xff0c;保持了原始内容不变&#xff0c;仅调整了格式以提升可读性&#xff1a; 行列式的线性性质&#xff08;加法拆分&#xff09; 这个性质说的是&#xff1a;如果行列式的某一行&#xff08;或某一列&#xff09;的所有…

JAVA基础编程练习题--50道

一&#xff1a;循环结构 1.1 for循环 水鲜花数 &#xff08;1&#xff09;题目 &#xff08;2&#xff09;难点 如何获取三位数的个位数 如何计算一个数的立方 判断两数值是否相等 &#xff08;3&#xff09;代码 最大公约数 &#xff08;1&#xff09;题目 &#xff08;2&…

leetcode 93. Restore IP Addresses

题目描述 93. Restore IP Addresses 代码 回溯法 class Solution {vector<string> res; public:vector<string> restoreIpAddresses(string s) {string IP;int part 0;backtracking(s,0,IP,part);return res;}void backtracking(const string &s,int start…

pytest+allure+allure-pytest 报告输出遇到的问题汇总

文章目录 前言问题一&#xff1a;module allure has no attribute severity_level问题二&#xff1a;ERROR:file or directory not found: ‐vs问题三&#xff1a;生成的 html 报告是空的&#xff0c;明明有测试用例执行完成&#xff0c;但报告没有显示数据 前言 pytestallure…

【Opencv+Yolo】_Day1图像基本处理

目录 一、计算机中的视觉&#xff1a; 二、Opencv基本操作&#xff1a; 图片基础处理&#xff1a; 视频基本处理&#xff1a; 图像截取&#xff08;截取&#xff0c;合并&#xff0c;只保留一个元素&#xff09; 图像填充 数值计算 图像融合 阈值判断 图像平滑 图像腐…