当前在1,可以走一级到2,或者走两级到3,到2的时候可以走一级也可以走两级,以此类推
1
2 3
3 4 4 5
4 5 5 6 5 6 6 7
5 6 6 7 6 7 7 8 6 7 7 8 7 8 8 9
…
可以发现,每季楼梯都可以通过上一级楼梯+1走到当前楼梯,后者前面第二级+2走到当前楼梯,因此,第n级的状态是有上一级和上两级的状态转移而来,得到Fn=Fn-1+Fn-2,可以用dp做这道题(dp的话前面这个公式就是状态转移方程),也可以发现这是斐波那契数的规律,可以用矩阵乘法写斐波那契过这题(虽然对这道题没有必要用矩阵乘法,但是如果题目范围大一点的话就有必要了,因此这里也加个矩阵乘法的解法),当然,因为范围n<=40,当然,对于方案数也可以选择用wang搜索的方法,但是这题测了一下,用暴搜一到n>=38的话就会t掉,38以下的数据点都能过
直接用总结出来的公式暴力打表输出答案:
#include<iostream>
#include<cstring>
#include<algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=50;
ll F[N];
void Init()
{
F[1]=1,F[2]=2;
for(int i=3;i<N;i++){
F[i]=F[i-1]+F[i-2];
}
}
int main()
{
Init();
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d", &n);
printf("%lld\n",F[n-1]);
}
return 0;
}
矩阵乘法解斐波那契数ac代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=2;
ll A[N][N],F[N];
void matrix1(ll a[N][N],ll b[N])
{
ll t[N]={0};
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
t[i]=(t[i]+a[i][j]*b[j]);
}
}
for(int i=0;i<N;i++)b[i]=t[i];
}
void matrix2(ll a[N][N],ll b[N][N])
{
ll t[N][N]={0};
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
for(int k=0;k<N;k++){
t[i][j]=(t[i][j]+a[i][k]*b[k][j]);
}
}
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
a[i][j]=t[i][j];
}
}
}
void mat_pow(ll n)
{
while(n){
if(n&1)matrix1(A,F);
matrix2(A,A);
n>>=1;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d", &n);
for(int i=0;i<N;i++){
F[i]=0;
for(int j=0;j<N;j++)A[i][j]=0;
}
A[0][0]=A[0][1]=A[1][0]=1,F[0]=1;
mat_pow(n);
printf("%lld\n",F[1]);
}
return 0;
}
直接暴搜会t掉,提供一下暴搜代码(t掉部分用打表写一下答案就不会t了,对于数据范围小于38的题可以用暴搜过)
#include<iostream>
#include<cstring>
#include<algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
int n;
ll res;
const int N=50;
bool vis[N];
void DFS(int u)
{
if(u>=n){
if(u==n)res++;
return;
}
if(!vis[u]){
vis[u]=true;
DFS(u+1);
DFS(u+2);
vis[u]=false;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d", &n);
res=0;
DFS(1);
if(n==1)res=0;
printf("%lld\n",res);
}
return 0;
}