题目链接:https://www.luogu.org/problem/P1192
设a[i]为走到第i阶的方法数
假设最多可以走k步,对任意x(x>=k)容易知道
1.a[x]=a[x-1]+a[x-2]+…+a[x-k]
2.a[x+1]=a[x]+a[x-1]+a[x-2]+…+a[x+1-k]=2*a[x]-a[x-k]
所以我们只需要先求出a[1]a[k]然后剩下的a[k+1]a[n]就可以直接通过上面的2式通过一次运算直接算出了 因为当数据比较大的时候k<<n,这时候复杂度近似为O(n)
至于a[1]~a[k]可以用一下方法求出
void init(){
a[0]=1; //a[0]表示走到第0阶(即起点)的方法数很容易理解为1
for(register int i=0;i<k;i++)
//从起点开始,访问每一阶级,假设当前访问的是第i阶,那么a[i+1]~a[i+k]要加上a[i],很容易理解
for(register int j=1;j<=k;j++) a[i+j]=(a[i+j]+a[i])%100003;
//可能会改变a[x](x>k)的值,但是没有影响,因为接下来是直接给a[k+1]~a[n]赋值的,所以会覆盖掉
}
//实际上对于a[1]~a[k],a[i](1<=i<=k)为2的(i-1)次方
//至于为什么大家可以根据我上面的init()函数带入几个k写一写很容易就懂了
以下是完整代码
#include <cstdio>
int n,k,a[100005];
void init(){
a[0]=a[1]=1;
for(register int i=2;i<=k;i++)
a[i]=(2*a[i-1])%100003;
}
int main(){
scanf("%d %d",&n,&k);
init();
for(register int i=k+1;i<=n;i++) a[i]=(2*a[i-1]+100003-a[i-1-k])%100003;
printf("%d
",a[n]);
return 0;
}