韩信点兵

样例输入:2 1 6    样例输出:Case 1:  41

                  2 1 3                     Case 2: No answer

①我的程序

#include<iostream>
using namespace std;
int main(void)
{
int a,b,c,kase=0;
scanf("%d%d%d",&a,&b,&c);
for(int i=10;;i++)
{
if(kase) printf("\n");
if(i>100)
{
printf("Case %d: No answer\n",++kase);
break;

}
if(i%3==a&&i%5==b&&i%7==c)
{
printf("Case %d: %d\n",++kase,i);
break;
}

}

return 0;

}

②运行结果

③问题

无法实现多组数据的输入输出,主要是多组数据的输入。在循环里输入会导致输出结果无限为0错误。

④解决途径

文件结束标志为EOF,在Windows下为Ctrl+Z+Enter,所以把之前的scanf("%d%d%d",&a,&b,&c);用一个while语句替换while(scanf ("%d%d%d",&a,&b,&c)!=EOF){}

用此语句代替是因为:EOF在scanf连用时代表-1的意思,当用到while(scanf()!=EOF),代表的意思是一直输入,直到scanf返回的值是-1时才会停止输入,也可以在while里面加上一些约束条件,使输入在特定的条件下就会停止,也可以在输入完成后按下 ,Ctrl+z,可以强行停止输入。

⑤改正后的代码

#include<iostream>
using namespace std;
int main(void)
{
int a,b,c,kase=0;
while(scanf ("%d%d%d",&a,&b,&c)!=EOF){
for(int i=10;;i++)
{
if(i>100)
{
printf("Case %d: No answer\n",++kase);
break;

}
if(i%3==a&&i%5==b&&i%7==c)
{
printf("Case %d: %d\n",++kase,i);
break;
}

}
}
return 0;

}

⑥改正后的运行结果

 

⑦另一种简便解法

 

数不大,可以用最简单的暴搜解决(我的方法)

但更巧妙的方法是用最小公倍数,韩信点兵的问题在明朝就出现了,明朝数学家程大位在他所著的《算法统宗》中就暗示了此题解法:

 

三人同行七十稀,

 

五数梅花甘一枝,

 

七子团圆正半月,

 

除百零五便得知。

 

甘一是21,正半月是15,除百零五的意思就是求105的余数。可以发现70是5和7的最小公倍数,21是3和7的最小公倍数,15是3和5的最小公倍数,105是3、5、7的最小公倍数。因此这四句口诀的意思就是用任意两数的最小公倍数乘第三个数并求和,对和求105的余数即可得到答案。

 

 代码

 

#include<iostream>
using namespace std;
int main(void)
{
int a,b,c,kase=0;
while(scanf ("%d%d%d",&a,&b,&c)!=EOF){
int sum;
sum = 70*a+21*b+15*c;
if (sum%105 <= 100)
printf ("Case %d: %d\n",++kase,sum%105);
else
printf("Case %d: No answer\n",++kase);
}
return 0;

}

 

 

 posted on 2018-07-17 14:56  slay  阅读(177)  评论(0编辑  收藏  举报