韩信点兵

韩信点兵

描述
相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值