我国古代数学家研究了很多涉及社会生活各个方面的有趣的计算问题,其求解通常归结为解不定方程或多元方程组;
百鸡问题
公元前五世纪,我国古代数学家 张邱健 在《张邱健算经》一书中记有一个有趣的数学问题:今有鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一,用百钱买鸡百只,问鸡翁、母、雏各几何?
这就是数学史上著名的“百鸡问题”;宋代杨辉的算数中有类似的问题,中古时其他各国也有相仿问题流传,例如印度算书和阿拉伯学者 艾布 · 卡米勒 的著作中都有百钱买百禽的问题,与《张邱健算经》中的题目几乎一样;
到了清代,研究百鸡术的人渐多,1815年 骆腾凤 使用“大衍求一术”解决了百鸡问题,在此前后时曰醇推广了百鸡问题,作《百鸡术衍》,从此百鸡问题和百鸡术才广为人知;
百鸡问题还有多种表述形式,如百僧吃百馒、百钱买百禽等;
百鸡问题的表述:用100个钱买100只鸡,其中公鸡5个钱1只,母鸡个钱1只,小鸡1个钱3只,问公鸡、母鸡与小鸡各买了多少只?
1.设计要点:
设公鸡、母鸡、小鸡数量分别为x、y、z,依题意列出方程组:
x+y+z=100;
5x+3y+z/3=100;
设计程序求解这个三元一次不定方程组的正整数解,采用对变量进行枚举来判断是否满足条件: x+y+z=100 and 5*x+3*y+z/3=100
对满足以上条件的解打印输出;
2.程序设计:
#include<stdio.h>
int main()
{
int x,y,z,n;
n=0;
for(x=1;x<=100/5;x++)
for(y=1;y<=100/3;y++)
for(z=3;z<=99;z+=3) /*利用z必须为3的倍数简化循环*/
if(x+y+z=100 && 5*x+3*y+z/3==100)
{
n++; /*以上条件同时满足时打印*/
printf("%d: x=%d, y=%d, z=%d \n",n,x,y,z);
break;
}
}
3.程序的改进:
上述程序中根据z必须为3的倍数确定z循环步长为3,可减少循环次数;
事实上,整个z循环都可以省略,用第一个条件来确定z=100-x-y即可;
对每一组x、y、z,如果满足条件:z%3=0 and 5*x+3*y+z/3=100,即可打印输出;
改进的双循环程序如下:
#include<stdio.h>
int main()
{
int x,y,z,n;
n=0;
for(x=1;x<=100/5;x++)
for(y=1;y<=100-x;y++)
{
z=100-x-y;
if(z>0 && z%3==0 && 5*x+3*y+z/3==100)
{
n++; /*满足条件时输出*/
printf("%d: x=%d, y=%d, z=%d\n",n,x,y,z);
break;
}
}
}
4.程序运行结果与说明:
1: x=4, y=18, z=78
2: x=8, y=11, z=81
3: x=12, y=4, z=84
若不要求每种鸡都有,只要把以上程序中的循环中的循环起始点改为0即可;
与百鸡问题相类似的还有我国民间流传的“百鱼百斤”趣题:
百条鲜鱼一百斤,大的每条重十斤;
中号一条一斤重,正好上席待宾客;
小的每条重一两,自己食用不嫌轻;
大中小号各多少,才是百鱼一百斤?
请修改以上程序求解“百鱼百斤”(注:古代一斤为16两);
羊犬鸡兔问题
我国古代《九章算术》中的“羊犬鸡兔”问题表述为:
5只羊、4只犬、3只鸡与2只兔共值1496个钱;
4只羊、2只犬、6只鸡与3只兔共值1175个钱;
3只羊、1只犬、7只鸡与5只兔共值958个钱;
2只羊、3只犬、5只鸡与1只兔共值861个钱;
求每只羊、犬、鸡、兔价值各为多少个钱(整数)?
1.设计要点:
设一只羊价为x,犬为y,鸡为z,兔为u,根据题意可得4元一次方程组:
5x+4y+3z+2u=1496;
4x+2y+6z+3u=1175;
3x+y+7z+5u=958;
2x+3y+5z+u=861;
在整数范围内(约定钱为整数个)解方程组,可以应用枚举判定完成求解;
设置x、y、z、u循环,对每一组x、y、z、u值判断是否同时满足4个方程;
设计中可精简一个循环,选取其中3个变量设置循环,另一个变量由其中一个方程决定,判断满足另3个方程,这样处理是适宜的,可以减少循环枚举次数;
2.程序设计:
#include<stdio.h>
int main()
{
int x,y,z,u;
printf("求解四元一次方程组的整数解: \n");
printf("5x+4y+3z+2u=1496\n");
printf("4x+2y+6z+3u=1175\n");
printf("3x+y+7z+5u=958\n");
printf("2x+3y+5z+u=861\n");
for(x=1;x<=1496/5;x++) /*改进x、z、u循环终值以减少循环次数*/
for(z=1;z<=(958-3*x)/7;z++)
for(u=1;u<=(958-3*x-7*z)/5;u++)
{
y=958-3*x-7*z-5*u; /*取y满足一个方程*/
if(y<0) /*判别另3个方程同时满足*/
break;
if(5*x+4*y+3*z+2*u=1496 && 4*x+2*y+6*z+3*u=1175 && 2*x+3*y+5*z+u=861)
{
printf("方程组的整数解为: \n");
printf("x=%d y=%d z=%d u=%d\n",x,y,z,u);
}
}
}
3.程序运行结果:
求解四元一次方程组的整数解:
5x+4y+3z+2u=1496
4x+2y+6z+3u=1175
3x+y+7z+5u=958
2x+3y+5z+u=861
方程组的整数解为:
x=177 y=121 z=23 u=29
即得羊犬鸡兔问题的答案为:羊价177个钱/只,犬价121个钱/只,鸡价23个钱/只,兔价29个钱/只;