1.问题描述:
话说这天韩信在项王手下吃了败仗,最后带着自己零散的部队撤出了战场。这个时候他想知道自己部队士兵的具体人数(当然他也不可能从项王手下带走超过100位士兵)。聪明的韩信不想直接清点自己军队的人数(再浪费时间估计这些士兵他也带不走了……),于是,他让士兵先后以三人一排、五人一排、七人一排的方式排队,每次排好队后,他只看一眼队伍的排尾人数(分别用a , b, c表示),就知道了总人数。现在聪明的你,如果给你三个非负整数a,b,c,你知道军队的总人数吗?已知总人数不超过100,不小于10。
2.问题分析:
首先我们看到这个问题,会第一时刻想到使用循环解决问题。在利用循环之前,首先要判断是否存在非法输入,即队尾士兵的数量,假设是n人一排,队尾数量不可小于0,不可大于等于n(假定队尾士兵数量为0是合法的,这个无伤大雅)。
接下来,通常情况下,我们会使用暴力枚举解决问题,即直接遍历0~100的数字,看哪个符合条件输出即可,当数字大于100还没有找到符合条件的数字,直接输出input error即可。
3.上代码:
#include <stdio.h>
int main(void)
{
int a, b, c;
int i;
scanf("%d,%d,%d",&a,&b,&c);
//1.先判断是不是存在非法输入 。
if(a<0||b<0||c<0||a>=3||b>=5||c>=7){
printf("input error");
return 0;
}
//2.暴力枚举,遍历10~100,看是否有符合条件的数字,存在则返回数值 。
for(i = 11; i < 100; i++){
if(i%3==a&&i%5==b&&i%7==c){
if(i>10&&i<100){
printf("%d",i);
return 0;
}
}
}
//3.程序运行到这一步说明没有符合条件的数字,返回即可。
printf("No answer");
return 0;
}
4.思考:
在这种情况下,暴力枚举造成的时间上的开销比较大,算法是不是可以进一步的优化?
这实际上是一个数学问题,分析:3、5、7的最小公倍数为105,故目标值不会大于105(105为一个循环)
易知,目标数 % 7 = c,则可设目标数 = 7*i + c, 每次的增量为7,可以大大减少运算量。
5.代码优化如下:
#include <stdio.h>
int main(void)
{
//分析,3、5、7的最小公倍数为105,故目标值不会大于105(105为一个循环)
int a, b, c;
int i;
scanf("%d,%d,%d",&a,&b,&c);
//1.先判断是不是存在非法输入 。
if(a<0||b<0||c<0||a>=3||b>=5||c>=7){
printf("input error");
return 0;
}
//2.目标数 % 7 = c,则可设目标数 = 7*i + c, 每次的增量为7,可以大大减少运算量。
i = 7 + c;
while(i<100){
if(i%3==a&&i%5==b&&i%7==c){
if(i>10&&i<100){
printf("%d",i);
return 0;
}
else{
printf("No answer");
return 0;
}
//增量为7
i += 7;
}
}
//3.程序进行到这一步说明没有符合条件的数字,直接返回即可。
printf("No answer");
return 0;
}