韩信点兵C语言实现的几种方法

6 篇文章 0 订阅
2 篇文章 0 订阅
                          韩信点兵C语言实现的几种方法

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

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

样例输入:
2 1 6
样例输出:
41
样例输入:
2 1 3
样例输出:
No Answer

分析:
从问题描述中可以看出,队尾人数等于士兵总人数除以每排士兵基数的余数。
解决思路:
选取一个整数,分别用选取的整数除以每个队形的每排士兵基数,得到每个队形的队尾人数,如计算出的所有队尾人数与题目中给出的队尾一致,若忽略最小值则找到了答案。
难点:
对于这个问题,已经找到了解决思路,但是如何选取整数十分重要,因为这将关系到我们程序的运行快慢。
方法一:
因为我们要找满足条件的最小值,所以我们采用循环的方式,从最小值10开始,然后加1,最大到最大值100,循环91次,如果找到便输出满足条件的最小值并结束循环。

 #include<stdio.h>
int main()
{
	int a, b, c;
	scanf("%d%d%d", &a,&b,&c);
	for(int i=10; i<101; i++)
	{
		if(i%3 == a)
		{
			if(i%5 == b)
			{
				if(i%7 == c)
				{
					printf("%d", i);
					return 0 ;
				}
			}
		}
	}	
	printf("No answer");	
	return 0;	
}

方法二:
针对方法一,我们做出如下改进,每排士兵基数最大为7,此时队尾人数为c,所以士兵总人数为7i+c(i为正整数),因此我们的循环从7+c开始,每次加7,最大到91+c或98+c为止,循环只有13或14次,较方法一减少大量运行时间。如果找到便输出满足条件的最小值并结束循环。(为什么不选择每排士兵基数最小3?大家思考一下)

 #include<stdio.h>
int main()
{
	int a, b, c;
	scanf("%d%d%d", &a,&b,&c);
	for(int i=7+c; i<101; i=i+7)
	{
		if(i%3 == a)
		{
			if(i%5 == b)
			{
				if(i%7 == c)
				{
					printf("%d", i);
					return 0 ;
				}
			}
		}
	}	
	printf("No answer");	
	return 0;	
}

方法三:
继续对方法二改进:
(1) 若c%3=a,设总人数为7i+c(i为正整数),(7i+c)%3=(7i%3+c%3)%3=(7i%3+c)%3=7i%3+b=b,则有7i%3=0,i=3n,所以总人数为21n+c。
此时,循环从21+c开始,每次加21,最大到84+c为止,循环只有4次,较方法二更加节省时间。
(2)若b%3=a,…,总人数为15n+b。
(3)若c%5=b,…,总人数为35n+c。
(4)若a%5=b,…,总人数为15n+a。
(5)若b%7=c,…,总人数为35n+b。
(6)若a%7=c,…,总人数为21n+a。

程序中只加入了(1)部分,其他部分也可加入,不过看起来程序特别长,但是执行效率在某些时候还是比较高效的。

#include<stdio.h>
int main()
{
	int a, b, c;
	scanf("%d%d%d", &a,&b,&c);
	if(c%3 == a)
	{
		for(int i=21+c; i<101; i=i+21)
		{
			if( i%5 == b)
			{
				printf("%d", i);
					return 0 ;
			}
		}
		printf("No answer");	
		return 0;	
	}
	for(int i=7+c; i<101; i=i+7)
	{
		if(i%3 == a)
		{
			if(i%5 == b)
			{
				if(i%7 == c)
				{
					printf("%d", i);
					return 0 ;
				}
			}
		}
	}	
	printf("No answer");	
	return 0;	
}
  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值