• #YBT整理 递推(二)


    重点题目:

    1、P1197 :山区建小学

    2、P1195 :判断整除

    3、P1192 :放苹果

    4、P1312 :【例3.4】昆虫繁殖

    5、P1313 :【例3.5】位数问题

    6、P1188 :菲波那契数列(2)

    P1189:Pell数列

    题目描述

    (Pell数列|a_{1},a_{2},a_{3},...的定义是这样的,a1=1,a_{2}=2,cdots,a_{n}=2a_{n-1}+a_{n-2}(n>2)。给出一个正整数k,要求Pell数列的第k项模上32767是多少。)

    【输入】

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

    【输出】

    n行,每行输出对应-一个输入。输出应是一一个非负整数。

    【输入样例】

    2
    1
    8
    

    【输出样例】

    1
    408
    

    思路

    还是用的矩阵乘法。

    代码

    #include "iostream"
    #include "cstdio"
    #include "algorithm"
    #include "cstring"
    #include "string"
    #include "cmath"
    #define int long long
    using namespace std;
    
    const int p = 32767;
    int n,a,b;
    
    struct matrix{
    	int a[4][4]={};
    	void print(){
    		for(int i = 0;i < 2; i++){
    			for(int j = 0;j < 2; j++){
    				cout << a[i][j] << ' ';
    			}
    			cout << endl;
    		}
    	} 
    }in,e;
    
    matrix operator *(matrix &a,matrix &b){
    		matrix c;
    		for(int i = 0;i < 2; i++){
    			for(int j = 0;j < 2; j++){
    				for(int k = 0;k < 2; k++){
    					(c.a[i][j] += a.a[i][k] * b.a[k][j] %p) %=p;
    				}
    			}
    		}
    		return c;
    }
    
    matrix Pow(matrix a,int x){
    	matrix tot = e;
    	while(x){
    		if(x & 1) tot = a * tot;
    		a = a * a;
    		x >>= 1;
    	}
    	return tot;
    }
    
    signed main(){
        int t;
        cin >> t;
        while(t--){
            cin >> n ;
            a = 2,b = 1; 
            
            e.a[0][0] = 1;e.a[0][1] = 1;
            
            in.a[0][0] = 0; in.a[0][1] = b;
            in.a[1][0] = 1; in.a[1][1] = a;
    
            matrix ans = Pow(in,n);
            
            int x = ans.a[1][1];
            cout << x << endl;
            }
    	return 0;
    }
    

    P1190 :上台阶

    看上面!

    P1191 :流感传染

    题目描述

    有一批易感人群住在网格状的宿舍区内,宿舍区为n*n的矩阵,每个格点为一个房间,房间里可能住人,也可能空着。在第一天,有些房间里的人得了流感,以后每天,得流感的人会使其邻居传染上流感,(已经得病的不变) ,空房间不会传染。请输出第m天得流感的人数。

    【输入】

    第一行一个数字n, n不超过100,表示有n*n的宿舍房间。

    接下来的n行,每行n个字符,’'表示第一天该房间住着健康的人, #表示该房间空着,'@' 表示第一天该房间住着得流感的人。

    接下来的一行是一个整数m, m不超过100。

    【输出】

    输出第m天,得流感的人数。

    【输入样例】

    5
    ....#
    .#.@.
    .#@..
    #....
    .....
    4
    

    【输出样例】

    16
    

    思路

    同上面

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    long long n,m;
    long long ans;
    long long a[200][200],b[200][200];
    long long mov[8][2] = {0,1,0,-1,1,0,-1,0,1,1,1,-1,-1,1,-1,-1};
    int main(){
        cin >> n;
        for(long long i = 1;i <= n; i++){
            for(long long j = 1;j <= n; j++){
                char c;
                cin >> c;
                if(c == '#')
                    a[i][j] = -1;
                if(c == '@')
                    a[i][j] = 1;
            }
        }
        // for(long long i = 1;i <= n; i++){
        //     for(long long j = 1;j <= n;j++){
        //         cout << a[i][j] << ' ';
        //     }
        //     cout << endl;
        // }
        cin >> m;
        for(long long k = 1;k < m; k++){
            for(long long i = 1;i <= n; i++){
                for(long long j = 1;j <= n; j++){
                    if(a[i][j] == -1){
                        b[i][j] = -1;
                        continue;
                    }
                    b[i][j] = a[i][j];
                    for(long long l = 0;l < 4; l++){
                        if(a[i+mov[l][0]][j+mov[l][1]] != -1){
                            b[i][j] += a[i+mov[l][0]][j+mov[l][1]];
                        }
                    }
                    if(b[i][j] > 0) b[i][j] = 1;
                }
            }
            for(long long i = 1;i <= n; i++){
                for(long long j = 1;j <= n; j++){
                    a[i][j] = b[i][j];
                    // cout << b[i][j] << " ";
                }
                // cout << endl;
            }
            // cout << endl;
        }
        for(long long i = 1;i <= n; i++){
            for(long long j = 1;j <= n; j++){
                if(a[i][j] > 0) ans++;
            }
        }
        cout << ans << endl;
        return 0;
    }
    

    P1192 :放苹果

    题目描述

    把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法? (用K表示) 5,1,1和1, 5,1是同一种分法。

    【输入】

    第一行是测试数据的数目t (0<=t<20) 。以下每行均包含二个整数M和N,以空格分开。

    【输出】

    对输入的每组数据M和N,用一行输出相应的K。

    【输入样例】

    1
    7 3
    

    【输出样例】

    8
    

    思路

    f[i][j]表示前i个盘子里面放j个苹果的数量,状态转移公式:

    [f[i][j] = f[i][j-1] + [i-j][j] ]

    解释:因为允许有空盘子存在,所以递归分为两种情况:有一个空盘子和没有空盘子

    有一个空盘子就是f[i][j-1],没有空盘子就是先往每个空盘子里面放一个,再把剩下的i-j个苹果放到j个空盘子里面,就是f[i-j][j]。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int a[12][12];
    int main()
    {
        int n,m,t;
        cin>>t;
    
        while(t>0)
        {
            --t;
            cin>>m>>n;
            a[0][0]=1;
            for(int i=0;i<=m;++i )
            for(int j=1;j<=n;++j)
               {
    
                   if(i<j)   a[i][j]=a[i][i];
                   else      a[i][j]=a[i][j-1]+a[i-j][j];
               }
               cout<<a[m][n]<<endl;
        }
        return 0;
    
    }
    

    P1193 :吃糖果

    魔改斐波那契。

    P1194 :移动路线

    题目描述

    X桌子上有一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。
    小明是个调皮的孩子,一天他捉来一只蚂蚁,不小心把蚂蚁的右脚弄伤了,于是蚂蚁只能向上或向右移动。小明把这只蚂蚁放在左下角的方格中,蚂蚁从左下角的方格中移动到右上角的方格中,每步移动一个方格。蚂蚁始终在方格矩阵内移动,请计算出不同的移动路线的数目。

    对于1行1列的方格矩阵,蚂蚁原地移动,移动路线数为1;对于1行2列(或2行1列)的方格矩阵,蚂蚁只需一次向右 (或向上)移动,移动路线数也为.....对于一个2行3列的方格矩阵,如下图所示:

    【输入】

    输入只有一行,包括两个整数m和n (0 《m+ns20),代表方格矩阵的行数和列数,m、之间用空格隔开。

    【输出】

    输出只有一行,为不同的移动路线的数目。

    【输入样例】

    2 3
    

    【输出样例】

    3
    

    思路

    [f[i][j] = f[i-1][j] + f[i][j-1]; ]

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int m,n;
    int f[20][20];
    int main(){
        cin >> m >> n;
        for(int i = 1;i <= n; i++) f[1][i] = 1;
        for(int j = 1;j <= m; j++) f[j][1] = 1;
        for(int i = 2;i <= m; i++){
            for(int j = 2;j <= n; j++){
                f[i][j] = f[i][j-1] + f[i-1][j];
            }
        }
        cout << f[m][n] << endl;
        return 0;
    }
    
  • 相关阅读:
    jmeter_分布式测试
    Locust性能测试_百度案例
    tkinter学习笔记_06
    tkinter学习笔记_05
    web前后端交互,nodejs
    Chrome Vue Devtools插件安装和使用
    line-height和height的区别
    网站头部导航
    屏蔽元素默认样式中的边距
    CSS Float(浮动)
  • 原文地址:https://www.cnblogs.com/Cao-Yucong/p/12468256.html
Copyright © 2020-2023  润新知