洛谷P1192 台阶问题

题目链接: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\n",a[n]);
    return 0;
}
posted @ 2019-08-24 10:13  如梦山河乀  阅读(136)  评论(0编辑  收藏  举报