递推小结

1312:【例3.4】昆虫繁殖


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 4463     通过数: 2077

【题目描述】

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

【输入】

x,y,z的数值。

【输出】

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

【输入样例】

1 2 8

【输出样例】

37

思路:

ps这个题好难懂啊,样例都看不懂qwq

对与样例,就是成虫此时在第0天,它第2,4,6,8天的时候会产卵,然后第2天的卵在第4天,变成成虫,然后在第5天可以产卵。

设a[i]表示第i天成虫的数量

具体见注释

代码如下:

#include<iostream>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int INF=0x3f3f3f3f;
const int N=105;
ll a[N];
int main(){
    int x,y,z;
    scanf("%d%d%d",&x,&y,&z);
    for(int i=0;i<x+2;i++)a[i]=1;
    //第1只成虫在第x天产地1批卵,卵在x+2天变成成虫
    //在此期间成虫数量都是1
    for(int i=x+2;i<=z;i++){
        a[i]=a[i-1]+a[i-x-2]*y;
        //第i天的成虫数量等于i-1天的成虫数量+第i天从卵变成成虫的数量
        //卵变成的成虫,在第i-2天的时候被孵化,其数量等于i-2-x天成虫数量*y
    }
    printf("%lld\n",a[z]);
}

1313:【例3.5】位数问题


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 3018     通过数: 1539

【题目描述】

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

【输入】

读入一个数N。

【输出】

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

【输入样例】

2

【输出样例】

73

思路:

设ji[i]表示i位数中有奇数个3的个数(位数是从右往左算)

ou[i]表示i位数中有偶数个3的个数

hin明显ji[1]=1(只有3)ou[1]=9

递推方程:

ou[i]=ji[i-1]+ou[i-1]*9(若i是最高位则*8,因为0不能开头)

ji[i]=ou[i-1]+ji[i-1]*9(若i是最高位则*8,因为0不能开头)

代码如下:

#include<iostream>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int INF=0x3f3f3f3f,mod=12345;
const int N=1005;
ll ou[N],ji[N];//ou[i]表示第i为有偶数个3的个数,ji表示第i为有奇数个3的个数
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
    ou[1]=9;ji[1]=1;
    int x=9;
    for(int i=2;i<=n;i++){
        if(i==n)x=8;
        ou[i]=(ou[i-1]*x%mod+ji[i-1])%mod;
        ji[i]=(ji[i-1]*x%mod+ou[i-1])%mod;
    }
    printf("%lld\n",ou[n]%mod);
    }
}

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


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 3400     通过数: 1359

【题目描述】

棋盘上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

思路:

递推公式:dp[i][j]=dp[i-1][j]+dp[i][j-1];

正常情况下,我们这样初始化:

for(int i=1;i<=max(n,m);i++){
        dp[i][0]=1;
        dp[0][i]=1;
}
dp[0][0]=0;

但是,这题里有我们不能到达的点,那么第0行,第0列这列点后的点都不可达!

还有就是找这些不可达点的时候注意不要数组越界哦~

代码如下:

#include<iostream>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int INF=0x3f3f3f3f,mod=12345;
const int N=25;
ll dp[N][N],yes[N][N];

void init(int x,int y){
    yes[x][y]=1;
    if(x-1>=0){
        yes[x-1][y+2]=1;
        if(y-2>=0)yes[x-1][y-2]=1;
    }
    if(x-2>=0){
        yes[x-2][y+1]=1;
        if(y-1>=0)yes[x-2][y-1]=1;
    }
    if(y-1>=0){
        yes[x+2][y-1]=1;
    }
    if(y-2>=0){
        yes[x+1][y-2]=1;
    }
    yes[x+1][y+2]=1;
    yes[x+2][y+1]=1;
}

int main(){
    int n,m,x,y;
    scanf("%d%d%d%d",&n,&m,&x,&y);
    init(x,y);
    dp[0][0]=0;
    for(int i=1;i<=n;i++){
        if(yes[i][0]){dp[i][0]=0;break;}
        else dp[i][0]=1;
    }
    for(int i=1;i<=m;i++){
        if(yes[0][i]){dp[0][i]=0;break;}
        else dp[0][i]=1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(yes[i][j])dp[i][j]=0;
            else {
                dp[i][j]=dp[i][j-1]+dp[i-1][j];
            }
        }
    }
    printf("%lld\n",dp[n][m]);
}

猜你喜欢

转载自blog.csdn.net/m0_37579232/article/details/84947270