兔子的启示:变量拆分

一对兔子,从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。假如兔子都不死,请问第1个月出生的一对兔子,第n个月有多少只兔子?

变量拆分法

通常的,对于这个问题,通常的求解方法是观察得出前两项和等于第三项,也就是斐波那契数列。但如果没有观察出这个结果,还有更直白的方式做这道题,如下

兔子总数按照性质拆分,分别分为:
A=出生了一个月兔子
B=出生了二个月兔子
C=成年兔子
兔子总数=A+B+C

不难发现,下一个月的
一月兔子=B+C(成年兔子生的)
二月兔子=A(本来一个月大的长成两个月大了)
成年兔子=B+C(已经成年的加上本来两个月大的长成的成年兔子)
兔子总数=上面三项的加和

表面上一步步推进的每月兔子数,事实上是它内部的变量(每种类型兔子是兔子总数的内部变量)按照一定的规律(上面写的下一个月的每种兔子的算法)进行自我更新(几个量进行一定计算后重新赋值给原来的每种兔子类型了)

对于这种重新赋值的情况,在代码上的做法可以是将原来的数据拷贝出来,进行计算后重新计算后填入,如下图:

\\A、B、C仍然是上面说过的意思
\\每个小写字母是大写字母数值的拷贝
int a=A,b=B,c=C;
A=b+c;
B=a;
C=b+c;
Sum=A+B+C;

那么对于我们要求的第n月兔子数,也就是Sum=A+B+C,用一个for循环就可以写出代码了。具体代码在文末。

总结:
1.对于一个变量,可以观察它能否拆分成“小项经过一定方式的运算”,这样解决问题的可能性会大一些,也会直接一些。
2.对于一些变量经过自身一些规律运算后自我更新的问题,可以先将其拷贝,用拷贝出来的数值运算后填入原来的变量里。

扩展:变量自我更新在递推数列中的应用

转回来讲,如果讲兔子问题用的是递推公式an+2=an+an+1来做,用变量更新来做:从开头开始,先把a3算出来,然后a,b,c分别表示a1,a2,a3,将a,b,c每个拷贝出一个备份copya,copyb,copyc,然后像上面一样给a,b,c重新赋值,重新赋值后每个变量表示的数列往后推一个,变成对应a2,a3,a4,以此类推。(其实这里的a用不上,可以不拷贝)
在这里插入图片描述
代码:

for(i=1;i<n;i++)
{copya=a;copyb=b;copyc=c;
a=copyb;
b=copyc;
c=copyb+copyc;}
printf("a[n]=%d",a);

总结:其实只要知道递推公式,无论那个递推式多么复杂,都可以用这种方法做。只需把相邻(不一定要严格相邻,像an=an-4+2an-2这种不完全是连在一起的递推公式也完全没问题,只要后来递推出来的那个值是唯一的就行了)看成一个整体,拷贝原变量,用拷贝出的数据进行一定运算后重新赋值给原变量就行了。每运算一次变量代表的a[i]变成a[i+1](也就是往后推一位)

文末附:变量拆分做法的代码

#include<stdio.h>
int main()
{
/*a=一个月大的兔子
b=两个月大的兔子 
c=成年兔子 
copya=a的拷贝
copyb=b的拷贝
copyc=c的拷贝
n=月份数
sum=每个月兔子总对数 */
int a=1,b=0,c=0,n=0,sum=0;
int copya,copyb,copyc;
printf("请输入月份数\n");
scanf("%d",&n);
int i;
for(i=1;i<=n;i++)
{copya=a,copyb=b;copyc=c;
a=copyb+copyc;
b=copya;
c=copyb+copyc; 
} 
sum=a+b+c;
printf("兔子总数为%d",sum);
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值