#include<stdio.h>
#include<iostream>
using namespace std;
const int N = 12;//定义所求月份
/*著名意大利数学家Fibonacci曾提出一个问题:有一对小兔子,从出生后第3个月起每个月都生一对兔子。
小兔子长到第3个月后每个月又生一对兔子。按此规律,假设没有兔子死亡,第一个月有一对刚出生的小兔子,
问第n个月有多少对兔子?*/
//总体思路是f(n)=f(n-2)+f(n-1) 即本月的兔子=本月新出生兔子+以前留下的老兔子
//因为2个月之前的兔子此时全部具有繁殖能力 因此新兔子的数量=f(n-2)
//又因为前一个月的兔子全部活下来了 因此本月的老兔子数量=f(n-1)
void RabbitBreeding1(int n);
void RabbitBreeding2(int n);
void RabbitBreeding3(int n);
//求最大公约数
//1.辗转相除法:取两个数中最大的数做除数,较小的数做被除数,用最大的数除较小数,
//如果余数为0,则较小数为这两个数的最大公约数,
//如果余数不为0,用较小数除上一步计算出的余数,直到余数为0,则这两个数的最大公约数为上一步的余数。
void GreatestCommonDivisor1();
//2.相减法:取两个数中的最大的数做减数,较小的数做被减数,用最大的数减去小数,
//如果结果为0,则被减数就是这两个数的最大公约数,
//如果结果不为0,则继续用这两个数中最大的数减较小的数,直到结果为0,则最大公约数为被减数。
void GreatestCommonDivisor2();
//3.穷举法:将两个数作比较,取较小的数,以这个数为被除数分别和输入的两个数做除法运算,
//被除数每做一次除法运算,值减少1,直到两个运算的余数都为0,则该被除数为这两个数的最大公约数。
void GreatestCommonDivisor3();
int main ()
{
RabbitBreeding1(N);
RabbitBreeding2(N);
RabbitBreeding3(N);
GreatestCommonDivisor1();
GreatestCommonDivisor2();
GreatestCommonDivisor3();
}
//c = a + b; a = b; b = c;做数据的迁移 每次循环只进行了一个月的递推 因此总共需要进行n次 ab代表1月和2月 因此循环部分为3->n
void RabbitBreeding1(int n)
{
int i, a = 1, b = 1, c = 0;
cout << "1月:" << a << endl << "2月:" << b << endl;
for(i = 3; i <= n; i++)
{
c = a + b;
a = b;
b = c;
cout << i << "月:" << c << endl;
}
cout << "\n第" << n << "月共有兔子:" << c << endl;
}
//c=a+b; a=b+c; b=c+a; 构造循环不变式 这样循环一次递推3步 循环次数减少 为n/3次
void RabbitBreeding2(int n)
{
int i, a = 1, b = 1, c = 0;
for(i = 1; i <= n / 3; i++)
{
c = a + b;
a = b + c;
b = c + a;
}
cout << "\n\n第" << n << "月共有兔子:" << c << endl;
}
//可以无需引入第三个变量 a=a+b;b=a+b; 此时循环一次递推2步
void RabbitBreeding3(int n)
{
int i, a = 1, b = 1;
for(i = 1; i <= (n - 2) / 2 ; i++)//因为ab有初始值 已经代表了2个月 因此所求月份是n-2 同时因为每次递推2步 因此/2
{
a = a + b;
b = b + a;
}
cout << "\n\n第" << n << "月共有兔子:" << b << endl;
}
//辗转相除法
void GreatestCommonDivisor1()
{
int a = 36, b = 5;//求a,b的最大公约数
int prea = a, preb = b;
int c = a % b;
while(c)
{
a = b;
b = c;
c = a % b;
}
cout << endl << prea << "和" << preb << "最大公约数是:" << b <<endl;
}
//相减法
void GreatestCommonDivisor2()
{
int a = 36, b = 5;//保证a>b;
int prea = a, preb = b;
int c = a - b;
while(c)
{
a = b > c ? b : c;//保证a>b;
if(a == b)//被减数>减数>差 此时a,b的值依次后延 即a=b, b=c;
b = c;
//不满足if条件说明b<c此时只需要a=c即可满足被减数>减数
c = a - b;
}
cout << endl << prea << "和" << preb << "最大公约数是:" << b <<endl;
}
//穷举法
void GreatestCommonDivisor3()
{
int a = 36, b = 5;
int mins = a > b ? b : a;//求出两数中较小的那个
while(a % mins || b % mins)//两个运算的余数都不为0 (德摩根)
{
mins--;
}
cout << endl << a << "和" << b << "最大公约数是:" << mins <<endl;
}