02-递推

本文通过四个示例详细介绍了递推算法在解决不同问题中的应用,包括菲波那契数列、昆虫繁殖、数字金字塔和位数问题。每个例子都提供了两种不同的解决方案,展示了递推思想的灵活性和实用性。递推算法在计算复杂度和效率方面具有优势,是解决动态规划和数学问题的有效工具。
摘要由CSDN通过智能技术生成

1、简单递推

1188:菲波那契数列(2)

【题目描述】

菲波那契数列是指这样的数列: 数列的第一个和第二个数都为1,接下来每个数都等于前面2个数之和。

给出一个正整数a,要求菲波那契数列中第a个数对1000取模的结果是多少。

【输入】

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a(1 <= a <= 1000000)。

【输出】

n行,每行输出对应一个输入。输出应是一个正整数,为菲波那契数列中第a个数对1000取模得到的结果。

【输入样例】

4

5

2

19

1

【输出样例】

5

1

181

1

<代码1>

#include<bits/stdc++.h>  
using namespace std;  
int a[1000001]={0,1,1};
int i,n,m;
int main()  
{
	for(i=3;i<=1000001;i++)//递推
	   a[i]=(a[i-1]+a[i-2])%1000;
	cin>>n;
	for(i=1;i<=n;i++)
	   {
			cin>>m;
			cout<<a[m]<<endl;
			}
	
	return 0;	
}

<代码2>

#include<bits/stdc++.h>
using namespace std;
int f[1000003];
int dfs(int x)//记忆化搜索
{
	if(f[x])return f[x];
	return f[x]=(dfs(x-2)%1000+dfs(x-1)%1000)%1000;
}
int main()
{
	int a,n;
	cin>>n;
	f[1]=f[2]=1;
	for(int i=1;i<=n;i++)
	{
		cin>>a;
	    cout<<dfs(a)<<endl;
	}
	return 0;
}

2、两数组递推

1312:【例3.4】昆虫繁殖

【题目描述】

科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强。每对成虫过x个月产y对卵,每对卵要过两个月长成成虫。假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后的第一个月不产卵(过x个月产卵),问过z个月以后,共有成虫多少对?0≤x≤20,1≤y≤20,X≤z≤50。

【输入】

x,y,z的数值。

【输出】

过z个月以后,共有成虫对数。

【输入样例】

1 2 8

【输出样例】

37

<代码>

#include<bits/stdc++.h>
using namespace std;
const int N=55;
long long a[N],b[N],x,y,z;
int main()
{
	cin>>x>>y>>z;
	z++;
	a[1]=1;
	for(int i=2;i<=z;i++)
	{
		if(i>x)b[i]=a[i-x]*y;
		a[i]=a[i-1]+b[i-2];
	}
	cout<<a[z];
	return 0;
}

3、二维递推

1258:【例9.2】数字金字塔

【题目描述】

观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。

在上面的样例中,从13到8到26到15到24的路径产生了最大的和86。

【输入】

第一个行包含R(1≤R≤1000),表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

所有的被供应的整数是非负的且不大于100。

【输出】

单独的一行,包含那个可能得到的最大的和。

【输入样例】

5

13

11  8

12  7   26

6   14  15  8

12  7   13  24  11

【输出样例】

86

<代码1>

#include<bits/stdc++.h>
using namespace std;
const int N=1100;
int a[N][N],n;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=i;j++)
		 cin>>a[i][j];
	for(int i=1;i<=n;i++)//顺推
	  for(int j=1;j<=i;j++)
		a[i][j]+=max(a[i-1][j-1],a[i-1][j]);
	int maxx=0;
	for(int i=1;i<=n;i++)maxx=max(maxx,a[n][i]);
	cout<<maxx<<endl;
	return 0;
}

<代码2>

#include<bits/stdc++.h>
using namespace std;
const int N=1100;
int a[N][N],n;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=i;j++)
		 cin>>a[i][j];
	for(int i=n-1;i>=1;i--)//逆推
	  for(int j=1;j<=i;j++)
		a[i][j]+=max(a[i+1][j],a[i+1][j+1]);
	cout<<a[1][1]<<endl;
	return 0;
}

4、按位递推

1313:【例3.5】位数问题

【题目描述】

在所有的N位数中,有多少个数中有偶数个数字3?由于结果可能很大,你只需要输出这个答案对12345取余的值。

【输入】

读入一个数N(N≤1000)。

【输出】

输出有多少个数中有偶数个数字3。

【输入样例】

2

【输出样例】

73

<代码>

#include<bits/stdc++.h>
using namespace std;
const int N=1100,mod=12345;
int a[N][2],n;
int main()
{
	cin>>n;
	a[1][0]=9,a[1][1]=1;//偶数3 奇数3
	for(int i=2;i<n;i++)
	  a[i][0]=(a[i-1][0]*9+a[i-1][1])%mod,
	  a[i][1]=(a[i-1][0]+a[i-1][1]*9)%mod;
	cout<<(a[n-1][1]+a[n-1][0]*8)%mod<<endl;
	return 0;
}

5、递推应用

1314:【例3.6】过河卒(Noip2002)

【题目描述】

棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B。现在要求你计算出卒从A点能够到达B点的路径的条数。

【输入】

给出n、m和C点的坐标。

【输出】

从A点能够到达B点的路径的条数。

【输入样例】

8 6 0 4

【输出样例】

1617

<代码>

#include<bits/stdc++.h>
using namespace std;
const int N=25;
long long f[N][N];
int g[N][N],n,m,x,y;
int dx[9]={0,-2,-1,1,2,2,1,-1,-2};
int dy[9]={0,1,2,2,1,-1,-2,-2,-1};
int main()
{
	cin>>n>>m>>x>>y;
	for(int i=0;i<9;i++)
	{
		int xx=x+dx[i],yy=y+dy[i];
		if(xx<0||xx>n||yy<0||yy>m)continue;
		g[xx][yy]=1;//马点
	}  
	f[0][0]=1;
	for(int i=0;i<=n;i++)
	  for(int j=0;j<=m;j++)
	  {
	  	if(i==0&&j==0)continue;//起点
		if(i==0&&g[0][j]==0)f[0][j]=f[0][j-1];//第一行
		if(j==0&&g[i][0]==0)f[i][0]=f[i-1][0];//第一列
		if(i&&j&&g[i][j]==0)f[i][j]=f[i-1][j]+f[i][j-1];//中间
	  }
    cout<<f[n][m]<<endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值