换硬币问题(百钱百鸡)+推理

题目描述

编写程序实现用一元硬币换成一分,两分,五分的硬币共50枚。

思路

假设一分,两分,五分的硬币各X,Y,Z枚。则有
1.X+Y+Z=50;
2,X+2Y+5Z=100;
3,X在(0,50),Y在(0,50),Z在(0,20)范围内
这里提一下O(n)算法,可以借助上述公式得出
Y=50-4Z;
X=3Z;

代码:

#include<stdio.h>
void method1()//O(n3)
{
	int ans=0;
	for(int i=0;i<=50;i++)//一分的数量 
		for(int j=0;j<=50;j++)//两分的数量 
			for(int k=0;k<=20;k++)//五分的数量 
				if(i+j+k==50 && i+2*j+5*k==100)
					printf("一分:%d 两分:%d 五分:%d\n",i,j,k),ans++;
	printf("总共有%d种方法\n",ans);
}
void method2()//O(n2)
{
	int ans=0;
	for(int i=0;i<=50;i++)//两分的数量 
	{
		for(int j=0;j<=20;j++)//五分的数量
		{
			int x=50-i-j;//一分的数量
			if(x>=0 && i+4*j==50)
			{
				printf("一分:%d 两分:%d 五分:%d\n",x,i,j);
				ans++;
			} 
		} 
	}
	printf("总共有%d种方法\n",ans);
}
void method3()//O(n)
{
	int ans=0;
	for(int i=0;i<=12;i++)//五分钱的数量 
	{
		int j=50-4*i;//两分钱 
		int k=3*i;//一分钱
		printf("一分:%d 两分:%d 五分:%d\n",k,j,i),ans++;
	}
	printf("总共有%d种方法\n",ans);
}
int main()
{
	//method1();
	//method2();
	method3();
	return 0;
}

题目描述

我国古代数学家张邱建在《算法》中出了一道题“鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。百钱百鸡,问鸡翁,鸡母,鸡雏各几何?”
现在假定各鸡种的价格不变,拥有的钱数为m,需要购买的鸡数为n,试求出所有可能的购买方案数。

input

每行对应一个测试样例,每一行包含2个数字,分别为n和m。最后一行包含2个-1,表示输入结束。

output

每组测试样例的结果输入占一行,输出可能购买方案的总数。

思路:

首先暴力来做这个题,设i为公鸡,j为母鸡,k为小鸡,就满足两个条件
1.n=i+j+k;
2.m=5i+3j+k/3;这里的k一定要是3的公倍数;

代码(n³)
#include<stdio.h>//这个算法的时间复杂度可以认为是O(n3) 
int main()
{
	int m,n;
	while(scanf("%d%d",&n,&m),n!=-1)
	{
		int cnt=0;
		for(int i=0;i<=n;i++)//i代表的公鸡数量 
			for(int j=0;j<=n;j++)//j代表的母鸡数量
				for(int k=0;k<=n;k++)//k代表小鸡数量
					if(i*5+j*3+k/3==m && k%3==0 && i+j+k==n) 
						cnt++;//printf("%d %d %d\n",i,j,k);
		printf("%d\n",cnt);
	}
	return 0;
}

很容易看出来这是一个n³的算法;如何改进,我们可以想到i,j,k是不独立的,满足m=5i+3j+k/3,所以k=3m-15i-9*j;时间复杂度就降了一维;

代码(n²)
#include<stdio.h>//假设我们能买到n个鸡,则小鸡的数量为k=n-i-j; m=i*5+j+k/3=>k=3*m-15*i-3*j;
int main()
{
	int m,n;
	while(scanf("%d%d",&n,&m),n!=-1)
	{
		int cnt=0;
		for(int i=0;i<=n;i++)
			for(int j=0;j<=n;j++)
			{
				int k=3*m-15*i-9*j;
				if(k>=0 && i+j+k==n) cnt++;//printf("%d %d %d\n",i,j,k);
			}	
		printf("%d\n",cnt);
	}
} 

已知
1.n=i+j+k;
2.m=5i+3j+k/3;这里的k一定要是3的公倍数;
推出
1.8k=6i-3m+9n;
2.8j=3m-n-14j;

代码(n)

#include<stdio.h>
int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m),n!=-1)
	{
		int cnt=0;
		for(int i=0;i<=m/5;i++)
		{
			int k=6*i-3*m+9*n;
			int j=3*m-n-14*i;
			if(k%8==0 && j%8==0 &&j>=0 && k>=0)
			{
				printf("%d %d %d\n",i,j/8,k/8);
				cnt++;
			}
		}
		printf("%d\n",cnt);
	}
	return 0;
}
发布了39 篇原创文章 · 获赞 1 · 访问量 570

猜你喜欢

转载自blog.csdn.net/qq_45249273/article/details/104400614