zoukankan      html  css  js  c++  java
  • [FZYZOJ 1600] [NOIP福建夏令营]台阶问题

    P1600 -- [NOIP福建夏令营]台阶问题

    时间限制:1000MS

    内存限制:131072KB

    Description

    有 N 级的台阶,你一开始在底部,每次可以向上迈最多 K 级台阶(最少 1 级),问到达第 N 级台阶有多少种不同方式。

    Input Format

    输入的仅包含两个正整数 N,K。

    Output Format

    输入仅包括 1 个正整数,为不同方式数,由于答案可能很大,你需要输出mod 100003 后的结果。

    Sample Input

    5 2
    

    Sample Output

    8

    Hint

    对于 20%的数据,有 N ≤ 10, K ≤ 3;

    对于 40%的数据,有 N ≤ 1000;

    对于 100%的数据,有 N ≤ 100000,K ≤ 100。

    【题解】

    首先,设f[i]为走到i的走法数量。

    那么到i的方案一定是由(i-k)~(i-1)这之中的所有方案构成(因为这中间的每一级都可以一次跨到i这个台阶)

    那么f[i]=sigma{f[i-j]} (0<=j<=k) f[0]=1;

    那么我们有了第一份代码,实际上已经可以AC了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int f[100001],n,k;
     4 int main() {
     5     scanf("%d%d",&n,&k);
     6     f[0]=1;
     7     for (int i=1;i<=n;++i) {
     8         for (int j=1;j<=i&&j<=k;++j)
     9             f[i]+=f[i-j], f[i]%=100003;
    10         f[i]%=100003;
    11     }
    12     printf("%d
    ",f[n]);
    13     return 0;
    14 }
    View Code

    我们看到,时间复杂度为O(NK),10000000,还是可以过的。

    我们发现,可以进行优化。

    设一个变量sum表示前缀和进行优化,注意如果i>k的时候,我们需要的不是0...i的所有前缀和!

    我们需要的只是部分的前缀和,所以要减去前面的,注意可能出现负数,加上后取模。

    那么,f[i]=sum,sum=(sum+f[i]-f[i-k-1]+MOD)%MOD (i>k)  

    那么,即可发现,时间复杂度优化到O(N)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int f[100001],n,k,sum=0;
     4 int main() {
     5     scanf("%d%d",&n,&k);
     6     f[0]=1;
     7     for (int i=1;i<=n;++i) {
     8         if(i>k) {
     9             sum-=f[i-k-1];
    10             sum=(sum+100003)%100003;
    11         }
    12         sum+=f[i-1];sum%=100003;
    13         f[i]=sum;
    14     }
    15     printf("%d
    ",f[n]);
    16     return 0;
    17 }
    View Code

    这两份代码,在评测机上评测的时间分别为 0.358s和0.009s,说明优化也是非常重要的。

    这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
  • 相关阅读:
    redis主从架构
    redis持久化
    git 首次push失败
    Java8 CompletableFuture
    Mac Item2自动远程连接服务器
    Java8 日期和时间类
    【LeetCode】31. 下一个排列
    【LeetCode】30. 串联所有单词的子串
    【LeetCode】29. 两数相除
    【LeetCode】28. 实现 strStr()
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/fzyzoj1600.html
Copyright © 2011-2022 走看看