中国剩余定理——AcWing 204. 表达整数的奇怪方式

2024-06-19 06:36

本文主要是介绍中国剩余定理——AcWing 204. 表达整数的奇怪方式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

中国剩余定理

定义

中国剩余定理最早出自我国古代的《孙子算经》,是数论中的一个重要定理。它描述了这样一种情况:在模运算下,对于一组线性同余方程组,存在唯一解的条件和求解方法。

运用情况

常用于在一些涉及到按不同模的余数条件下求解问题。比如在密码学、计算数论、计算机科学等领域中,当需要处理多个模条件相关的计算时,常常会用到中国剩余定理。

注意事项

  • 要求各个模之间互质,否则定理不直接适用,可能需要进行一些转化处理。
  • 在计算过程中要保证计算的准确性,尤其是涉及到较大数的运算时。

解题思路

AcWing 204. 表达整数的奇怪方式   

题目描述

AcWing 204. 表达整数的奇怪方式 - AcWing

运行代码

#include <iostream>
#define int long long
using namespace std;
int n;
int exgcd(int a, int b, int &x, int  &y)
{if(!b){x = 1, y = 0;return a;}int d = exgcd(b, a % b, y, x);y -= a / b * x;return d;
}
signed main()
{bool st = true;cin >> n;int a1, m1;cin >> a1 >> m1;for(int i = 2; i <= n; i ++ ){int a2, m2, k01, k02, d;cin >> a2 >> m2;d = exgcd(a1, a2, k01, k02);if((m2 - m1) % d) {st = false;break;}k01 = k01 * (m2 - m1) / d;k01 = (k01 % (a2 / d) + (a2 / d)) % (a2 / d);m1 += a1 * k01;a1 = a1 / d * a2;}if(st) cout << (m1 % a1 + a1) % a1 << endl;else cout << -1 << endl;return 0;
} 

代码思路

  1. 类型定义与变量初始化

    • 使用 #define int long long 将整型变量默认定义为长整型,以处理大数。
    • 定义全局变量 n 表示同余方程的数量。
  2. 扩展欧几里得算法(exgcd): 实现了扩展欧几里得算法,用于求解形如 ax + by = gcd(a, b)ax+by=gcd(a,b) 的方程。返回值 d 是 aa 和 bb 的最大公约数(GCD),同时通过引用参数 xy 返回系数。这个函数是解决CRT的关键,用于寻找模数之间的关系。

  3. 主函数(main)

    • 首先读入同余方程的数量 n
    • 初始化第一个方程的系数 a1 和模数 m1
    • 对于每个后续的方程(从第二个到第 n 个),执行以下操作:
      • 读取当前方程的系数 a2 和模数 m2
      • 使用 exgcd 函数计算 a1 和 a2 的最大公约数 d,以及对应的系数 k01k02
      • 检查是否存在解:如果 (m2 - m1)(m2−m1) 不能被 d 整除,则说明无解,标记 st 为 false 并跳出循环。
      • 如果有解,根据中国剩余定理调整 m1 和 a1,使得它们分别表示合并后的同余方程的临时解和新模数。
    • 最后,根据 st 的值输出结果:如果为 true,则输出满足所有同余条件的最小非负整数解;否则,输出 -1 表示无解。

改进思路

  1. 使用更明确的变量名:虽然简短的变量名让代码紧凑,但更具有描述性的名称可以提高代码的可读性。例如,可以将 a1, a2, m1, m2 等变量名改为 current_coefficient, next_coefficient, current_modulus, next_modulus 等。

  2. 避免全局变量:全局变量 n 可能导致代码的维护和理解难度增加,尤其是在大型项目中。可以考虑将其作为函数参数传递。

  3. 优化解的计算和输出

    • 直接计算最终解而不仅仅是累积操作。在循环结束后,可以计算最终的 x(即满足所有同余方程的解)并直接取模,避免最后对 a1 进行额外的模运算。
    • 输出解时,使用 % 运算符可能两次取模,实际上 (m1 % a1 + a1) % a1 可以简化为 (m1 % a1),因为当 m1 < 0 时,(m1 + a1) % a1 已经保证结果非负。
  4. 增加错误处理和注释:对于输入验证(如检查模数是否两两互质、是否为正整数等)添加更多的错误处理逻辑,并在关键步骤添加注释,帮助读者理解算法逻辑。

  5. 模块化设计:将中国剩余定理的求解过程封装成一个独立的函数,而不是全部放在 main 函数中,这样可以提高代码的复用性和可测试性。

  6. 考虑大数运算库:如果要处理非常大的数字,可以考虑使用专门的大数运算库(如 GMP 库),这会比直接使用 C++ 内置数据类型更高效且支持更大的数值范围。

  7. 优化扩展欧几里得算法的实现:虽然现有实现是标准的,但在某些特定情况下,可以通过一些小技巧进一步优化,比如利用幂次计算减少递归深度,或是迭代法替代递归以节省栈空间。

这篇关于中国剩余定理——AcWing 204. 表达整数的奇怪方式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1074276

相关文章

如何突破底层思维方式的牢笼

我始终认为,牛人和普通人的根本区别在于思维方式的不同,而非知识多少、阅历多少。 在这个世界上总有一帮神一样的人物存在。就像读到的那句话:“人类就像是一条历史长河中的鱼,只有某几条鱼跳出河面,看到世界的法则,但是却无法改变,当那几条鱼中有跳上岸,进化了,改变河道流向,那样才能改变法则。”  最近一段时间一直在不断寻在内心的东西,同时也在不断的去反省和否定自己的一些思维模式,尝试重

idea lanyu方式激活

访问http://idea.lanyus.com/这个地址。根据提示将0.0.0.0 account.jetbrains.com添加到hosts文件中,hosts文件在C:\Windows\System32\drivers\etc目录下。点击获得注册码即可。

创新、引领、发展——SAMPE中国2024年会在京盛大开幕

绿树阴浓夏日长,在这个色彩缤纷的季节,SAMPE中国2024年会暨第十九届国际先进复合材料制品原材料、工装及工程应用展览会在中国国际展览中心(北京朝阳馆)隆重开幕。新老朋友共聚一堂,把酒话桑麻。 为期4天的国际学术会议以“先进复合材料,引领产业创新与可持续化发展”为主题,设立了34个主题分会场,其中包括了可持续化会场、国际大学生会场、中法复合材料制造技术峰会三个国际会场和女科技工作者委员会沙龙,

以canvas方式绘制粒子背景效果,感觉还可以

这个是看到项目中别人写好的,感觉这种写法效果还可以,就存留记录下 就是这种的背景效果。如果想改背景颜色可以通过canvas.js文件中的fillStyle值改。 附上demo下载地址。 https://download.csdn.net/download/u012138137/11249872

vue同页面多路由懒加载-及可能存在问题的解决方式

先上图,再解释 图一是多路由页面,图二是路由文件。从图一可以看出每个router-view对应的name都不一样。从图二可以看出层路由对应的组件加载方式要跟图一中的name相对应,并且图二的路由层在跟图一对应的页面中要加上components层,多一个s结尾,里面的的方法名就是图一路由的name值,里面还可以照样用懒加载的方式。 页面上其他的路由在路由文件中也跟图二是一样的写法。 附送可能存在

vue子路由回退后刷新页面方式

最近碰到一个小问题,页面中含有 <transition name="router-slid" mode="out-in"><router-view></router-view></transition> 作为子页面加载显示的地方。但是一般正常子路由通过 this.$router.go(-1) 返回到上一层原先的页面中。通过路由历史返回方式原本父页面想更新数据在created 跟mounted

【第十三课】区域经济可视化表达——符号表达与标注

一、前言 地图最直接的表达就是使用符号表达。使用符号可以把简单的点线面要 素渲染成最直观的地理符号,提高地图的可读性。只要掌握了 ArcGIS 符号制 作的技巧,分析符号并总结出规则,就可以制作符合要求的地图+符号。 (一)符号的选择与修改 符号的选择在制图中至关重要,使用符号选择器对话框可从多个可用样式 中选择符号,并且每个符号都有一个标签用来描述其图形特征,如颜色或类型, 利用这些标签可

LeetCode--204 计数质数

题目 统计所有小于非负整数 n 的质数的数量。 示例 示例:输入: 10输出: 4解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 class Solution {public:int countPrimes(int n) {if (n <= 2) return 0;int cnt = 0;vector<bool> isPrime(n, true);

二叉树三种遍历方式及其实现

一、基本概念 每个结点最多有两棵子树,左子树和右子树,次序不可以颠倒。 性质: 1、非空二叉树的第n层上至多有2^(n-1)个元素。 2、深度为h的二叉树至多有2^h-1个结点。 3、对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为n0,度为2的结点数为n2,则n0 = n2 + 1。 满二叉树:所有终端都在同一层次,且非终端结点的度数为2。 在满二叉树中若其深度为h,则其所包含

七种排序方式总结

/*2018.01.23*A:YUAN*T:其中排序算法:冒泡排序,简单排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序*/#include <stdio.h>#include <math.h>#include <malloc.h>#define MAXSIZE 10000#define FALSE 0#define TRUE 1typedef struct {i