当前位置:网站首页>中国剩余定理 个人理解
中国剩余定理 个人理解
2022-07-28 05:26:00 【我们一起摆烂鸭】
问题
一个小例子,一个数x 符合以下条件(x mod 3 = 2 ,x mod 5 = 3, x mod 7 =2)求这个数的最小值。
解决方法(除数互质的时候)
看了许多的题解分析,主要的思路如下:
1、问题分解:设 x= x1 + x2 + x3 :(x = 2 (mod 3)的意思为 x mod 3 后的结果为 2)
- x1 满足(= 2 (mod 3),= 0 (mod 5),= 0 (mod 7 ) )
- x2 满足(= 0 (mod 3),= 3 (mod 5),= 0 (mod 7 ) )
- x3 满足(= 0 (mod 3),= 0 (mod 5),= 2 (mod 7 ) )
如此设置后的结果一定是满足 x 的要求的。
2、继续拆分:x1 = 2 * y1、 x2 = 3 * y2 、 x3 = 2 * y3。
- y1 (=1 mod 3,=0(mod 5),=0(mod 7))
- y2 (=0 mod 3,=1(mod 5),=0(mod 7))
- y3 (=0 mod 3,=0(mod 5),=1(mod 7))
我们在求余数为一时比较方便应该是
3、此时 x = 2 * y1+ 3 * y2 + 2 * y3。
如何求 yi?记三个除数(3,5,7)的最小公倍数为 n 。一下两种方案
- 对于y1 可知它是 5与7 的公倍数。我们y1从35缓慢增加,每次增加35,判断是否满足y1 mod 3 = 1。满足则找到y1。其他的同理。
- 对于y1 我们有以下要求满足的条件 i * y1 - j * 3 = 1(有的写的是i * y1 + j * 3 =1 原因是j 可能取负号)。其余的同理。
此类问题代码解决方案(除数互质时)
a = [3,5,7] ##a 为除数
m = [2,3,2] ##m 为余数
n = 1
for i in a: ## n为最小公倍数
n *= i
ans = 0
for i in range(3):
k = 0 # k % a[i] 需要等于1
while True:
k += n//a[i] ## k每次增加的值为 最小公倍数n除开a[i]的值
if k % a[i] == 1:
break
ans += m[i] * k ## 要求的值为其余m[i],就用k 乘上m[i]即可。结果加上ans
ans %= n ## ans 存放各第二类分割情况的结果的和,求最小,就模上n
print(ans)如果时除数互质的情况,还是很好解决的。
下面我们来看除数,不互质的情况。
2022年蓝桥杯省赛python B组 B题。题目如下。

看到题目的第一眼,我其实感觉昂,就这就这,我直接一个一个暴力找总是能找出来的吧。结果确实我暴力跑了三十多分钟还是没有跑出来.....
通过剩余定理,我们首先要确定的是其除数互质,但是在这里面的数是不互质的。成倍数关系的数我们能知道,取最小的值即可。(比如上述除数为2 时余数为1,除数为4时余数也为1。他们表达虽然差不多,但是更大的数-余数中的信息包含的更多。)
我们先找2~49中的质数。
(71条消息) 素数筛 python_我们一起摆烂鸭的博客-CSDN博客_python 素数筛
可知结果为【 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 】
由题目可知 a = [ i for i in range(2,50)]
m =
[1, 2, 1, 4, 5, 4, 1, 2, 9, 0, 5, 10, 11, 14, 9, 0, 11, 18, 9, 11, 11, 15, 17, 9, 23, 20, 25, 16, 29, 27, 25, 11,17, 4, 29, 22, 37, 23, 9, 1, 11, 11, 33, 29, 15, 5, 41, 46]
a = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
m = [1, 2, 1, 4, 5, 4, 1, 2, 9, 0, 5, 10, 11, 14, 9, 0, 11, 18, 9, 11, 11, 15, 17, 9, 23, 20, 25, 16, 29, 27, 25, 11,
17, 4, 29, 22, 37, 23, 9, 1, 11, 11, 33, 29, 15, 5, 41, 46]
nm = []
for i in a:
nm.append(m[i - 2])
print(nm)
n = 1
for i in a: ## n为最小公倍数
n *= i
ans = 0
print(n)
for i in range(len(a)):
k = 0 # k % a[i] 需要等于1
while True:
k += n // a[i] ## k每次增加的值为 最小公倍数n除开a[i]的值
if k % a[i] == 1:
break
ans += nm[i] * k ## 要求的值为其余m[i],就用k 乘上m[i]即可。结果加上ans
ans %= n ## ans 存放各第二类分割情况的结果的和,求最小,就模上n
print(ans)
for i in range(2, 50):
if ans % i != m[i - 2]:
print(i, m[i - 2])
其运行的结果如下:

哈哈哈,答案没错。又多了一个猜题的技巧了:遇见不会的就填日期了hhhh。
扩展:
看到最后就有一些聪明的好兄弟要说了:“啊,为什么就要这样互质呢?我直接全部放进去不还是可以?”。enmmm有点道理。我们举个例子 a = 【2,3,10】m =【1,2,9】,啊很简单呀,直接口算我们就知道答案是 29 。但是如果是直接莽用剩余定理呢?我们就会发现 30 就是 2 的倍数,所以就不可能找到一个30 的倍数使其除 2 == 1。所以呢?一定要互质!性质一好吧!这时又会好兄弟要说:“啊,我去掉了9,为什么答案算的11呢?这不对呀,你是不是在框我?” 嗯这时就要看我之前说的,大的数-余数中包含的信息更多。可是为什么在本题中我用小数也求出了正确的答案了呢?因为题目给的是从2 ~ 49 连续的数。其中任意一个和数都能是其中某些质数的积。而其几个小的乘数-余数 的信息能组合为大数- 余数的信息。就相当于无损去除。而本例子中的10 没有 其他的数相乘能得到他,所以将其去除时就丢失了一些信息。
本例: a = [ 2, 3 ,10 ] m = [ 1,2 ,9] 其答案是29 .我们反推其因子。10 //2 == 5。29%5 =4。我们用5- 4 来代替 10 - 9。即 a = 【2,3,5】,m = 【1,2,4】用中国剩余定理,结果就是29。
所以我们能知道 在连续的除数中我们直接保留质数即可,但是要是除数不连续(某些除数不能被其他除数相乘得到)那我们就要保留大的除数了。性质二好吧!
言后:
一定要养成随手保存的好习惯呀,QAQ,我就是这个扩展这里有点小问题,就习惯性的按了下ctrl + z 结果后面的都没了。刚才细后言时,鼠标又把那两个字的位置滑错了,差点又按了ctrl+z,还好忍住了。言后就言后吧,就不改了。。。。
边栏推荐
猜你喜欢
随机推荐
气传导蓝牙耳机哪个好、气传导蓝牙耳机排行榜
[PTA----输出全排列]
Five categories of IP addresses
2022-05-24 use of spiel
【C语言】自定义结构体类型
New Selenium
suger BI 创建任务
gerapy 使用
做气传导耳机最好的是哪家、最好的气传导耳机盘点
Leetcode 刷题日记 剑指 Offer II 048. 序列化与反序列化二叉树
2022-07-19 Damon database connection instance, execution script, system command
Find the network address and broadcast address of the host according to the IP address and subnet mask
Treasure plan TPC system development DAPP construction
关于时间复杂度,你不知道的都在这里
Use and safe shutdown of qthread thread in QT
开放式耳机有哪些、四款音质超好的气传导耳机推荐
2021-11-10
2022-05-15 基于jwt令牌token
【学习笔记】链表操作
Pyppeteer is recognized to bypass detection









