luogu1192:台阶问题:递推+优化

题目链接:有一个简化版本的题目:noi题库3525台阶问题
本文主要介绍了:
思路1 递推的朴素思维O(n*k)的相应解法和代码;
思路2 递推的优化O(n)的相应分析和代码;

另外还有记忆化递归,还有拓展数据之后的矩阵乘法,有兴趣的同学可以自行前往。


题目大意:
1 在走楼梯的时候,每次可以上1-k级,从地面开始走到第n级,有多少种方案数。


解题思路1:朴素直观:O(n*k)
1 当前如果是第 x 级,可以从 x-1,x-2,x-3....x-k,这 k 级楼梯走上来,所以,只要双重循环枚举就可以了;
2 要注意细节就是楼梯是从0开始的,没有负数;
3 记得取模;
上代码:

//luogu1192:台阶问题:朴素的递推 
//时间复杂度:n*k 

#include
#define mo 100003
using namespace std;
int n,k,ans=0;
int f[100005];

int main()
{
	scanf("%d %d",&n,&k);
	memset(f,0,sizeof(f));
	f[0]=f[1]=1;
	for(int i=2;i<=n;i++)
	{
		for(int j=max(0,i-k);j

解题思路2:观察分析与线性优化:O(n)
1 观察以下三句话:
当前是第 x     级,可以从                x-1,x-2,x-3....x-k+2,x-k+1,x-k,这 k 级楼梯走上来;
当前是第 x +1级,可以从           x,  x-1,x-2,x-3....x-k+2,x-k+1,        这 k 级楼梯走上来;
当前是第 x +2级,可以从 x+1,x,x-1,x-2,x-3....x-k+2,                    这 k 级楼梯走上来;

2 是否发现了相邻两次很多运算是有交集的呢?
3 然后可以得出以下简单的推算过程:

式子1:a[x]    =        a[x-1]+a[x-2]+...+a[x-k+1]+a[x-k] ;
式子2:a[x+1]=a[x]+a[x-1]+a[x-2]+...+a[x-k+1] ;

由式子1和式子2可以得出式子3:a[x+1]=a[x]*2-a[x-k] ;

将式子3下降一级,可推算出: a[x]=a[x-1]*2-a[x-k-1] (当x>k的时候成立)

4 当x(x-1)的台阶都可以上到x,所以:

式子1:a[x]    =        a[x-1]+a[x-2]+...+a[0] ;
式子2:a[x+1]=a[x]+a[x-1]+a[x-2]+...+a[0] ;

由式子1和式子2可以得出式子3:a[x+1]=a[x]*2;

将式子3下降一级,可推算出:a[x]=a[x-1]*2 (当x<=k的时候成立)

5 因为运算过程有负数,需要最后要进行负数排除;


上代码:

//luogu1192台阶问题:递推+优化
//时间复杂度O(n) 
//通过观察,将多次类似的前k项累加进行降维优化
//因为有减法,注意最后的排除负数的操作
 
#include
#define mo 100003
using namespace std;
int n,k,ans=0;
int a[100005];

int main()
{
	scanf("%d %d",&n,&k);
	a[0]=a[1]=1;
	
	for(int i=2;i<=k;i++)
	{
		a[i]=a[i-1]*2%mo;
	}
	for(int i=k+1;i<=n;i++)
	{
		a[i]=a[i-1]*2-a[i-k-1];
		a[i]%=mo;
	}
	
	printf("%d",(a[n]+mo)%mo);//排除负数 
	
	return 0;
}

 

 

 

 

 

 

 

你可能感兴趣的:(题解,大礼包,递推,luogu,题表)