您的位置:首页 > 其它

趣味数学问题的算法实现

2017-09-13 16:01 351 查看

一.袋鼠跳跃问题

问题描述:

有一只袋鼠,它跳跃一次的方式只有两种:①一次跳1米 ②一次跳3米,现在有一段10米长的路,袋鼠从起点开始跳,问到终点有多少种不同的跳跃方式?

问题分析:

10米其实通过枚举就能够计算出来,但是我们要做的是给出计算任何距离的算法,从而得到一个普遍的结论。

如果没有看出规律,可以一步一步分析。首先我们设剩余的距离为n,对应的不同跳跃方式为f(n)种,袋鼠肯定要跳第一次,有两种跳法,1米和3米,跳过以后的方式加一起等于f(n),即f(n)=f(n-1)+f(n-3),第二次跳又有两种方式,如此递归,最后对剩下的路程做判断,如果剩下1米,则只有一种方式,2米同样,3米则有两种方式。

算法实现:

#define N 10
int f(int n)
{
int m;
if(n==1||n==2) m=1;
if(n==3) m=2;
if(n>3) m=f(n-1)+f(n-3);
return m;
}
main()
{
printf("%d: %d\n",N,f(N));
}


运行结果如下:



可以手动验算一下,结果是正确的,我们变换N的取值,结果也都是可靠的。这个算法是采用递归调用实现的,但是递归调用涉及到栈的进出,耗费大量时间,所以效率不高,可以采用循环的方式进行,就是将递归放到循环中,此处不给出算法了。

二. 数字反转问题

问题描述:

有一个四位数,它的各位数字翻转以后组成新的四位数,原来的四位数是新四位数的4倍,求这个四位数。

问题分析:

本题涉及到各个位上数字的拆分和重组,所以要用到常见的数字拆分的算法,然后用数组盛装,再进行重组,最后判断并输出。

算法实现:

#define N 4
main()
{
int i,a,b,n,t,k,m;
short s
;
for(i=0,a=1;i<N-1;i++) a*=10; b=a*10;
for(n=a;n<b;n++)
{
t=n; i=0; do{s[i++]=t%10; t/=10;} while(t); //①
for(i=N-1,k=1,m=0;i>=0;i--) {m+=s[i]*k; k*=10;}
if(n==4*m) printf("%d = 4 * %d\n",n,m);
}
}


运行结果如下:



程序中的①处用到了标准的拆分数字的算法
do{s[i++]=t%10; t/=10;} while(t);
是采用原数依次除以10,得到的余数即为原数的各位数字。

三. 数学黑洞问题

问题描述:

任给出一个四位以内的数k0,用它的各位数字由大到小重新排列成一个数m,再减去它的反序数rev(m),得出数k1=m-rev(m),然后,继续对k1重复上述变换,得数k2.如此进行下去,可以发现,无论k0是多大的数, 只要各位数字不全相同,最多进行7次上述变换,就会出现四位数6174,也就是数学黑洞。

问题分析:

本题与上一题基本类似,只是在未知最后结果是6174的情况下,不能在程序中出现有关6174的声明,所以需要声明一个flag用来标记是否两次的运算结果相同,因为6174按上述运算一次的结果还是6174。

算法实现:

#define N 4
main()
{
int i,fg,t,n,j,a,b,c,k; short s
;
printf("please enter a number:");
scanf("%ld",&n);
do
{
i=fg=0; t=n;
do{s[i++]=t%10; t/=10;} while(t);
for(j=i;j<N;j++) s[i]=0;
for(i=0;i<N-1;i++)
for(j=i+1;j<N;j++)
{
if(s[i]<s[j])
{
t=s[i]; s[i]=s[j]; s[j]=t;
}
}
for(i=N-1,a=0,b=0,k=1;i>=0;i--)
{
a+=s[i]*k;
b+=s[N-i-1]*k;
k*=10;
}
c=a-b;
if(c!=n)
{
printf("%d - %d = %d\n",a,b,c);
n=c;
fg=1;
}
}
while(fg);
}


多次变换输入值,运行结果如下:







以上是几个与数学问题相关的算法实现,几乎所有数学问题都可用计算机来模拟解决,日常关注这些数学问题并思考如何用算法解决是一件很有趣的事。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: