韩信点兵

引子

早晨跑步的时候,突然想到韩信点兵这个问题,想了下 不知道如何去解答这个问题,一直停留在听说阶段,于是上班的时候就特意查了一下。原来它的学名 叫做中国剩余定理。

剩余定理:顾名思义就是和余数有关的操作
解决问题:
·有一次战斗后,韩信要清点士兵的人数。让士兵三人一组,就有两人没法编组;五人一组,就有三人无法编组;七人一组,就有两人无法编组。那么请问这些士兵一共有几人?
·在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3 余2),五五数之剩三(除以5 余3),七七数之剩二(除以7 余2),问物几何?”

解决这个问题,需要学习两个相关的定理
1.几个数相加,如果存在一个加数,不能被整数a整除,那么他们的和,就不能被整数a整除
2.两数不能整除,若被除数扩大(或缩小)N倍,而除数不变,则其余数也同时扩大(或缩小)相同的倍数

求解过程

1.求出最小公倍数

剩余问题的前置条件都是质数,所以此处直接相乘,关于最大公约数 最小公倍数的求解问题,我会在下一篇单独讲 传送过去
A = 3x5x7 = 105

2.求各个数对应的基础数
  1. 105÷3 = 35
    35÷3 = 11.....2
    35就是基础数,基础数就是满足题目要求的数,本题目要求 除以3余2,现在余数刚好是2,则35即为基础数

  2. 105÷5 = 21
    21÷5 = 4.....1
    此时余数是1,不符合除以5余3的要求,因此要根据定理2 把余数扩大3倍得到3,那么被除数也扩大3倍 得到21x3=63, 那么基础数就是63

  3. 105÷7=15
    15÷7=2....1 , 同理根据定理2,我们得到基础数是30

3.把得到的基础数加起来

为什么要这样做呢?利用就是上面提到的定理1。
35+63+30 = 128

对于3来说,可以把63+30的和看作一个整体,应该他们都可以被3整除。看着上面写出的三个数的特征,运用定理1来说,就是在35的基础上加上一个可以被3整除的倍数,那么得到的结果依然还是满足原先的性质的,就是128除以3还是余2的。同理,对于5还说,这个数被除之后会剩余3;对于7来说,被除之后剩余2。所以说,我们当前得到的这个数是满足题目要求的一个数。但是这个数是不是最小的,那就不一定了。
4.减去最小公倍数A (在比最小公倍数大的情况下)

最小公倍数顾名思义,一定是一个同时被几个数整除的最小的一个数,所以减去它剩余下来的余数还是符合题意要求的。当然也同样可以运用定理1来解释,只不过是加法变成了减法,道理还是一样的。

128-105 = 23 那么最小数就是23了

    int a[] = {3,5,7};
    int b[] = {2,3,2};
    
    int aLength = sizeof(a) / sizeof(int);
    int bLength = sizeof(b) / sizeof(int);
    if (aLength != bLength) {
        printf("不符合原则");
        return;
    }
    
    //1.求最小公倍数
    int cAllSum = 1;
    for (int i = 0; i < aLength; i++) {
        cAllSum = cAllSum * a[i];
    }
    
    //2.将当前基础数累加
    int cBaseSum = 0;
    for (int i = 0; i < aLength; i++) {
        //计算当前基础数
        int cCurrentBaseSum = cAllSum / a[i];
        //求当前余数
        int cCurrentYushu = cCurrentBaseSum % a[i];
        //目标余数
        int cGiveYushu = b[i];
        //根据定理2 求出当前基础数
        if (cCurrentYushu < cGiveYushu) {
            cCurrentBaseSum = cCurrentBaseSum * (cGiveYushu/cCurrentYushu);
        }
        cBaseSum = cBaseSum + cCurrentBaseSum;
    }
    
    //3.求复合条件的最小数
    while (cBaseSum > cAllSum) {
        cBaseSum -= cAllSum;
    }

参考文章1

你可能感兴趣的:(韩信点兵)