韩信点兵python程序_韩信点兵计算公式与代码

本文介绍了韩信点兵问题的历史背景及数学描述,通过古代算法和现代的中国剩余定理来解决问题。提供了详细的解题步骤和Python代码实现,帮助理解并解决此类余数问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

韩信点兵计算公式与代码

问题描述:

淮安民间传说着一则故事——“韩信点兵”,其次有成语“韩信点兵,多多益善”。

韩信带1500名兵士打仗,战死四五百人,站3人一排,多出2人;站5人一排,多出4人;站7人一排,多出6人。韩信很快说出人数:1049。

问题重述:

上述问题使用数学语言其实可以描述如下:

假设一个数为X,则1000

X%3 = 2

X%5 = 4

X%7 = 6

让求X。

问题解法:

其实韩信点兵问题,在古代已经有了解法。《孙子算经》有几句乘法口诀:三人同行七十稀, 五树梅花廿一枝, 七子团圆正半月, 除百零五便得知。

这句话的意思就是用被除数是3的余数(2)与70相乘,被除数是5的余数(4)与21相乘,被除数是7的余数(6)与15相乘,最后如果没在范围之内,就加减若干次105就可以得到答案。

所以算法是这样的:2*70+4*21+6*15=314人

314+105+105+105+105+105+105+105=1049人。

其中105是三个被除数的公倍数,即3*5*7=105,那么70,21,15是怎么来的呢?

现代人们解决这个问题用的是中国剩余定理。定理内容可以上网看到,这里不再多说,直接上公式。

上面算式的70,其实就是先让两个被除数相乘,比如被除数5*7=35,然后检查(35*1)除以剩余的那个被除数3是否余1,如果余1,则记下倍数为1;如果不为1,在检查(35*2)除以3是否余1,如果余1,则记下倍数为2,否则接着增加倍数继续判断。

因此,5*7=35,判断(35*1)%3 == 2 != 1,故判断(35*2)%3 ==1,记下倍数为2,35*2=70。

以此类推,

3*7=21,判断(21*1)%5==1,记下倍数为1,21*1=21。

3*5=15,判断(15*1)%7==1,记下倍数为1,15*1=15。

然后乘上另一项的余数再相加:

70*2+21*4+15*6=314。

最后再求出三个被除数的公倍数:3*5*7=105,通过加若干次105,使结果满足范围。

公式如下:

将题目抽象出来:X在(n,m)之间,并且X满足以下等式:

X%a = i

X%b = j

X%c = k

让求X。

第一步:

先求三个倍数x1,x2,x3,初始值三个数都为1,求出满足以下等式的x1,x2,x3。

(b*c*x1) % a == 1

(a*b*x2) % c == 1

(a*c*x3) % b == 1

第二步:

计算三个等式s1,s2,s3

s1 = (b*c*x1) * i

s2 = (a*b*x2) * k

s3 = (a*c*x3) * j

第三步:

求出三个被除数的公倍数s4

s4 = a*b*c

第四步:

计算s = s1+s2+s3

第五步:

根据X所在的范围(n,m),通过将s加减若干次s4,使s满足n<=s<=m。则最终结果s即为所得。

韩信点兵python代码如下:

print('------------------------韩信点兵------------------------')

print("请输入第一组被除数与余数(用空格隔开):")

a,i = map(int,input().split())

print("请输入第二组被除数与余数(用空格隔开):")

b,j = map(int,input().split())

print("请输入第三组被除数与余数(用空格隔开):")

c,k = map(int,input().split())

print("请输入该数的范围:")

n,m = map(int,input().split())

x1=x2=x3 = 1 #表示倍数

s4 = a*b*c #三个被除数的公倍数

s1=s2=s3 = 1 #每项的结果

t1=t2=t3 = False #用于判断余数是否为1

while True: #计算出每一项中的倍数x1,x2,x3

t1 = (b*c*x1) % a == 1

t2 = (a*b*x2) % c == 1

t3 = (a*c*x3) % b == 1

if(not t1):

x1+=1

if(not t2):

x2+=1

if(not t3):

x3+=1

if(t1 and t2 and t3):

break

s1 = (b*c*x1) * i #第一项的结果

s2 = (a*b*x2) * k #第二项的结果

s3 = (a*c*x3) * j #第三项的结果

# print(s1,s2,s3,s4)

s = s1+s2+s3 #s为计算的最终结果

print("该数为:",end=' ')

while True: #判断该数是否在(n,m)范围里,如果不再通过加减若干次的公倍数,使其处于范围里

if(s>n and s

print(s)

break

elif(s

s=s+s4 #如果小于下界,则加上公倍数,直到不小于

elif(s>m):

s=s-s4 #如果大于上界,则减去公倍数,直到不大于

elif(s==n or s==m):

print(s)

break

原文链接:https://blog.csdn.net/weixin_43982422/article/details/108540223

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值