2017程序设计练习题之递推专题

A题

//dp思想,也可以用递推思想,用a[i][j]表示有多少钟方法到(i,j)所以前一步肯定式(i-1,j)或(i,j-1)所以到达(i,j)就有a[i-1][j]+a[i][j-1]种
//a[i][0] = 1;a[0][i] = 1;
//然后不断从左上往右下递推过去
#include<bits/stdc++.h>

using namespace std;
const int maxn = 35;
long long  a[maxn][maxn];
int main()
{
    for(int i = 0;i < maxn;i++)a[i][0] = 1,a[0][i] = 1;
    for(int i = 1;i <maxn;i++){
        for(int j = 1;j < maxn;j++){
            a[i][j] = a[i][j-1] + a[i-1][j];
        }
    }
    int n,m;
    while(~scanf("%d%d",&n,&m)&&(n+m)){
        printf("%I64d\n",a[n][m]);
    }
}

B题

//首先k个全部错排有错排公式 d[i] = (i-1)(d[i-1) + d[i-2]);
//如果最后一个错排前n-1件有k-1件错排那个最后一个也要错排,如果后一个不用错排前N-1件k件错排,也就是杨辉三角c[i][j] = c[i-1][j-1]+c[i-1][j]
//然后两者乘积即是答案
#include<cstdio>
using namespace std;
const int N = 1001;
const int mod = 1000000007;
#define ll long long
ll d[N], c[N][N];
int main() {

    d[2] = 1;
    for(int i = 3; i < N; i ++)
        d[i] = (i - 1) * (d[i-1] + d[i-2]) % mod;
    //求组合数
    for(int i = 1; i < N; i ++)
        c[i][0] = c[i][i] = 1;
    for(int i = 2; i < N; i ++)
        for(int j = 1; j < i; j ++)
            c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mod;
    int n, k;
    while(~scanf("%d%d", &n, &k), n + k){
        if(k==0){puts("1");continue;}
        printf("%I64d\n", d[k] * c[n][k] % mod);
    }
    return 0;
}

C题

//斐波那契额
#include<bits/stdc++.h>

using namespace std;
int a[50];
int main(){
    a[1] = 2;
    a[2] = 3;
    for(int i = 3;i <= 40;i++){
        a[i] = a[i-1] + a[i-2];
    }
    int n;
    while(~scanf("%d",&n)&&n){
        printf("%d\n",a[n]);
    }
}


D题

//a[n] = a[n-1] + a[n-2] + 2^(n-2)
//前n-1位满足n位肯定可以,当倒数第二位为0时有a[n-2]种,当倒数第1,2是11时前n-2位就可以随便拍
#include<stdio.h>
#include<string.h>
#define mod 1000000007
#define m 1000001
int a[m];
int p[m];
int main()
{
    int i,j;
    p[0]=0;p[1]=0;p[2]=1;
    for(i=3;i<m;i++)
        p[i]=p[i-1]*2%mod;
    a[1]=0;a[2]=1;a[3]=3;
    for(i=4;i<m;i++)
        a[i]=((a[i-1]+a[i-2])%mod+p[i])%mod;
    scanf("%d",&j);
    while(j--)
    {
        int n;
        scanf("%d",&n);
        printf("%d\n",a[n]);
    }
}


E题

//你要算出从0到i段的L的数量,LO的数量,LOV的数量,LOVE的数量。假设dp[i][1]表示0到i这一段字符串中LO的数量,那么在0到i+1段中的LO有两种,一种是LO完全位于0到i段,另一种是L位于前i段,O位于i+1处。这样就可以递推了。其它类似
#include<bits/stdc++.h>

using namespace std;

#define mod 1000000007
const int maxn = 1001;
int dp[maxn][4];
char s[maxn];

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        int len = strlen(s);
        memset(dp,0,sizeof(dp));
        if(s[0] == 'L')dp[0][0] = 1;
        for(int i = 1;i < len ;i++){
            dp[i][0] = dp[i-1][0];
            dp[i][1] = dp[i-1][1];
            dp[i][2] = dp[i-1][2];
            dp[i][3] = dp[i-1][3];
            if(s[i] == 'L'){dp[i][0] = (dp[i-1][0]+1)%mod;}
            if(s[i] == 'O'){dp[i][1] = (dp[i-1][1]+dp[i-1][0])%mod;}
            if(s[i] == 'V'){dp[i][2] = (dp[i-1][2]+dp[i-1][1])%mod;}
            if(s[i] == 'E'){dp[i][3] = (dp[i-1][3]+dp[i-1][2])%mod;}
        }
        printf("%d\n",dp[len-1][3]);
    }
    return 0;
}


F题

//n=1时:m
//n=2时:m*(m-1)
//n=3时:m*(m-1)*(m-2)
//n>3时:

//若n-1与1颜色不同,则f[n-1]是排列好的,n号方块有m-2种颜色可涂  f[n]+=f[n-1]*(m-2)
//若n-1与1颜色相同,则f[n-2]是排列好的,n号方块有m-1种颜色可涂  f[n]+=f[n-2]*(m-1)
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int MOD=1000003;
int m,n;
long long int f[3000];

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(f,0,sizeof(f));
        f[1]=m;f[2]=m*(m-1)%MOD;f[3]=m*(m-1)*(m-2)%MOD;
        if(n>3)
        for(int i=4;i<=n;i++)
        {
            f[i]=(f[i-1]*(m-2)%MOD+f[i-2]*(m-1)%MOD)%MOD;
        }
        printf("%d\n",f[n]%MOD);
    }
    return 0;
}

G题

//暴力左子树节点的个数 然后递推
#include<stdio.h>
#define N 101
#define MOD 1000000007
int main()
{
    long long s[N];
    int i,j,n;
    s[0] = 1;
    for(i=1;i<=100;i++)
    {
        s[i]=0;
        for(j=0;j<i;j++)
        {
            n=s[j]*s[i-j-1]%MOD;
            s[i]+=n;

        }
        s[i]%=MOD;

    }
    while(scanf("%d",&n)!=EOF&&n!=-1)
    {
        printf("%I64d\n",s[n]);
    }
}


H题

//奇数无解 偶数时 F[N] = 4 * F[N-2] - F[N-4]
#include<bits/stdc++.h>

using namespace std;
const int maxn = 1010;
const int mod = 100003;
int f[maxn];
int main(){
    f[2] = 3;
    f[4] = 11;
    int n;
    for(int i = 6;i < maxn;i+=2)f[i] = ((4*f[i-2])%mod -f[i-4]+mod)%mod;
    while(~scanf("%d",&n)&&n){
        if(n&1){puts("0");continue;}
        printf("%d\n",f[n]);
    }
    return 0;
}

I题

//dp[i][j] = dp[i-1][j-1] + dp[i-1]][j]
#include<bits/stdc++.h>

using namespace std;
const int maxn = 40;
int a[maxn][maxn];
void dp(){

    for(int i=1;i<35;i++)
    a[i][0]=a[i][i]=1;

    for(int i=1;i<35;i++)
      for(int j=1;j<i;j++)
       a[i][j]=a[i-1][j]+a[i-1][j-1];


}
int main(){
    int k,n,m,i,j,s;
    scanf("%d",&k);
    dp();
    while(k--){
     scanf("%d%d",&n,&m);

     if((n-m)%2!=0) printf("0\n");
     else{
         s=(n-m)/2;
         dp();
         printf("%d\n",a[n][s]);
     }
    }
}

posted @ 2017-06-09 23:12  adfae  阅读(652)  评论(0编辑  收藏  举报