• ZOJ-3725 Painting Storages 动态规划


    题意:给定一个数N,表示有N个位置,要么放置0,要么放置1,问至少存在一个连续的M个1的放置方式有多少?

    分析:正面求解可能还要考虑到重复计算带来的影响,该题适应反面求解。设dp[i][j]表示到前 i 为后导 1 个数为 j 的方案数,于是有动态规划方程:

    dp[i][0] = sum{ dp[i-1][0... min(i-1, M) ] };
    dp[i][j] = dp[i-1][j-1]  其中 j != 1

    单单根据这个方程时间度为O(N*M),还是不足以在有限的时间内解出该问题。通过观察我们发现方程可以简化,即后一层的和值是上一层和值的两倍减去上层的最后一个值。于是可以维护一个最后一个值得队列,然后计算出首行的和值即可。注意首行是表示状态数达到M个的行。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    
    typedef long long LL;
    const int mod = int(1e9)+7;
    int N, M;
    queue<int>q;
    int pp[100005];
    
    LL _pow(LL a, int b) {
        LL ret = 1;
        while (b) {
            if (b & 1) ret = (ret * a) % mod;
            b >>= 1;
            a = (a * a) % mod;
        }
        return ret;
    }
    
    void gao() {
        int ret = 2;
        while (!q.empty()) q.pop();
        pp[0] = 1, pp[1] = 1;
        q.push(pp[0]);
        q.push(pp[1]);
        for (int i = 2; i < M; ++i) {
            pp[i] = (1LL * pp[i-1] * 2) % mod;
            ret = (1LL * ret + pp[i]) % mod;
            q.push(pp[i]);
        }
        for (int i = M; i <= N; ++i) {
            q.push(ret);
            ret = (1LL * ret * 2 - q.front() + mod) % mod;
            q.pop();
        }
        printf("%d
    ", (1LL * _pow(2, N) - ret + mod) % mod);
    }
    
    int main() {
        while (scanf("%d %d", &N, &M) != EOF) {
            if (N == 0 || M > N) {
                puts("0");
                continue;
            }
            if (M == 0) {
                printf("%d
    ", _pow(2, N));
                continue;
            }
            if (M == 1) {
                printf("%d
    ", (_pow(2, N)-1+mod)%mod);
                continue;
            }
            gao();
        }
        return 0;
    }
  • 相关阅读:
    HDOJ_2709_Sumsets
    HDOJ_2012_素数判定
    HDOJ_2011_大二写_水仙花树
    HDOJ_2010_大二写_水仙花数
    HDOJ_1290_大二写_献给杭电五十周年校庆的礼物
    HDOJ_2047_阿牛的EOF牛肉串
    HDOJ_2041_大二写_超级电梯
    HDOJ_2044_大二写_一只小蜜蜂...
    HDOJ_2046_骨牌方格_大二写
    HDOJ 2013_大二写
  • 原文地址:https://www.cnblogs.com/Lyush/p/3202778.html
Copyright © 2020-2023  润新知