动态规划基础题(第1题):被变换的菲波那切数列

碎碎念

  • 最近开始学习动态规划,相比之前学习的算法,诸如:枚举、贪心、全搜索等算法要复杂不少,这个山头不好攻。
  • “自己选的路,跪着也要走下去”,这话不是我说的,是老码农对我说的,上了贼船下船难啊。

标签

  • 动态规划、菲波那切数列

合集

  • 【动态规划】基本DP
  • 【数学】

题目地址

C - Typical Stairs

  • https://atcoder.jp/contests/abc129/tasks/abc129_c

问题描述

There is a staircase with N steps. Takahashi is now standing at the foot of the stairs, that is, on the 0-th step. He can climb up one or two steps at a time.

However, the treads of the a 1 _1 1-th, a 2 _2 2-th, a 3 _3 3-th, … \ldots …, a M _M M-th steps are broken, so it is dangerous to set foot on those steps.

How many are there to climb up to the top step, that is, the N-th step, without setting foot on the broken steps? Find the count modulo 1 000 000 007.

Constraints

  • 1≤N≤105
  • 0≤MN−1
  • 1 ≤ \leq a 1 _1 1 < a 2 _2 2 … < a M _M M ≤ \leq N-1

Input

Input is given from Standard Input in the following format:

N M
a1
a2
 .
 .
 .
aM

Output

Print the number of ways to climb up the stairs under the condition, modulo 1 000 000 007.


Sample Input 1

6 1
3

Sample Output 1

4

There are four ways to climb up the stairs, as follows:

  • 0→1→2→4→5→6
  • 0→1→2→4→6
  • 0→2→4→5→6
  • 0→2→4→6

Sample Input 2

10 2
4
5

Sample Output 2

0

There may be no way to climb up the stairs without setting foot on the broken steps.


Sample Input 3

100 5
1
23
45
67
89

Sample Output 3

608200469

Be sure to print the count modulo 1 000 000 007.

思路

  • 基于菲波那切数列改编的题目

  • 基于动态规划思路可以解题

题解

小码匠题解1

  • 这个题解:共有36个测试点,只有3个测试点没过,悲剧,暂时我还不知道哪里错了。
void coder_solution() {
    // 提升cin、cout效率
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    const long long mod = 1000000007;
    int n, m;
    cin >> n >> m;
    vector<int> vi(m);
    vector<long long> dp(n + 1);
    long long ans = 0;
    dp[0] = 1;
    dp[1] = 1;
    for (int i = 0; i < m; i++) {
        cin >> vi[i];
        if (vi[i] == 1) {
            dp[1] = 0;
            ans++;
        }
    }

    for (int i = 2; i <= n; i++) {
        if (i == vi[ans]) {
            dp[i] = 0;
            ans++;
        } else {
            dp[i] = (dp[i - 1] + dp[i - 2]) % mod;
        }
    }
    cout << dp[n];
}

小码匠题解2

  • 这个是看了题解后又修改后的代码,AC了
void coder_solution() {
    // 提升cin、cout效率
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    const long long mod = 1000000007;
    int n, m, temp;
    cin >> n >> m;
    vector<bool> vb(n, false);
    vector<long long> dp(n + 1);
    dp[0] = 1;
    dp[1] = 1;
    for (int i = 0; i < m; i++) {
        cin >> temp;
        vb[temp - 1] = true;
        if(temp == 1) {
            dp[1] = 0;
        }
    }

    for (int i = 2; i <= n; i++) {
        if (!vb[i - 1]) {
            dp[i] = (dp[i - 1] + dp[i - 2]) % mod;
        }
    }
    cout << dp[n];
}

参考题解

#include<bits/stdc++.h>

using namespace std;
const int N = 1e5 + 7, mod = 1e9 + 7;
int n, m, a[N], f[N];

int main() {
    
    scanf("%d%d", &n, &m);
    for (int i = 1, x; i <= m; i++) {
        scanf("%d", &x), a[x] = 1;
    }
    
    f[0] = 1;
    for (int i = 1; i <= n; i++) {
        if (!a[i]) {
            f[i] = (f[i - 1] + f[i - 2]) % mod;
        }
    }
    printf("%d\n", f[n]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小码匠和老码农

喜欢作者

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值