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;
}