#YBT整理 递推(二)
重点题目:
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-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
思路
代码
#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;
}