韩信点兵

来源:互联网 发布:路由器访客网络是什么 编辑:程序博客网 时间:2024/05/20 18:03

韩信点兵

描述
相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入3个非负整数a,b,c ,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100 。

输入
输入3个非负整数a,b,c ,表示每种队形排尾的人数(a<3,b<5,c<7)。例如,输入:2 4 5
输出
输出总人数的最小值(或报告无解,即输出No answer)。实例,输出:89
样例输入

2 1 6

样例输出

41

由题
我们已经知道了总兵数x对3,5,7取模得到的余数a,b,c
则可列出一个同余方程组
x≡a(mod 3)
x≡b(mod 5)
x≡c(mod 7)
通过题意列出方程组,最后可以解得x

用求解同余方程组的思路涉及到以下知识:

  • 数论倒数
  • 孙子定理

依据孙子定理

若有
x≡a1(mod m1)
x≡a2(mod m2)
x≡a3(mod m3)
.
.
.
x≡an(mod mn)
且m1,m2…mn两两互质

令M=m1*m2*…*mi
Mi=M/mi (1<=i<=n)
再求得每一个Mi的数论倒数为ti
则有
这里写图片描述为x的解集

具体思路如下:

已知
x≡a(mod 3)
x≡b(mod 5)
x≡c(mod 7)

M=3*5*7
Ma=M/3;
Mb=M/5;
Mc=M/7;

对于每一个Ma,Mb,Mc;
求他们的数论倒数ta,tb,tc;
最后列式
x=k*M+a*ta*Ma+b*tb*Mb+c*tc*Mc (k取整数值并且能使x大于零)
即可通过找到符合条件的k值,来求得x

求数论倒数的方法:

设Ma对于p的数论倒数为ta,有
ta=Ma^(p-2) (mod p)
即可求得数论倒数

以上为解题思路,解题过程如下:

设x为总的兵数,当输入a=2,b=1,c=6时
依题列方程组
x≡2(mod 3)
x≡1(mod 5)
x≡6(mod 7)
M=3*5*7=105
Ma=5*7=35
Mb=3*7=21
Mc=3*5=15
ta=35^(3-2)(mod 3)=2
tb=21^(5-2)(mod 5)=1
tc=15^(7-2)(mod 7)=1
∴x=105k+70a+21b+15c=105k+251
且总人数不小于10,不超过100
也就是k=-1或-2,取合适的值即可

无解

因为3,5,7两两互质,因此方程组有解,
但取值区间100-10+1=91<105
所以无解的情况应是x不在取值区间内

代码如下:

#include <stdio.h>#include <stdlib.h>#include <math.h>#include <time.h>int main(){    int a,b,c,sum;    while(scanf("%d %d %d",&a,&b,&c)==3){        sum=70*a+21*b+15*c-105;        if(10<=sum&&sum<=100){            printf("%d\n",sum);        }else if(10<=sum-105&&sum-105<=100){            printf("%d\n",sum-105);        }else{            printf("No answer\n");        }    }    return 0;}
0 0