P6394 樱花,还有你

题目链接

Solution

最暴力的 dp:设 (f_{i,j}) 表示到第 (i) 棵树下恰好摘取 (j) 朵樱花的方案数。转移方程如下:

[f_{i,j}=sum_{k=1}^j f_{i-1,k} ]

特别注意的是,需要满足 (s_i ≥ j - k)

这样就得到了一个 T 飞的程序。接下来又又又是前缀和优化...注意一下边界,既有上界又有下界。

优化完之后,你又会发现数组开不下了,因此还需要滚动数组。

然后这题就做完了。

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;

const int N = 233333;
const long long mod = 10086001;
LL n, k, sum = 0, ans = 0, s[N], g[N], f[2][N];

int main()
{
    scanf("%lld%lld", &n, &k);
    for(int i = 1; i <= k; i++) scanf("%lld", &s[i]), sum += s[i];
    if(sum < n) { printf("impossible"); return 0; }
    f[0][0] = f[1][0] = 1;
    for(int i = 1; i <= k; i++)
    {
        f[i & 1][0] = 1;
        for(int j = 1; j <= n; j++) f[i & 1][j] = 0;
        for(int j = 0; j <= n; j++) g[j] = (g[j - 1] + f[(i - 1) & 1][j] + mod) % mod;
        for(int j = 1; j <= n; j++)
        {
            if(j - s[i] - 1 >= 0) f[i & 1][j] = (f[i & 1][j] + g[j] - g[j - s[i] - 1] + mod) % mod;
            else f[i & 1][j] = (f[i & 1][j] + g[j] + mod) % mod;
        }
        ans = (ans + f[i & 1][n] + mod) % mod;
    }
    printf("%lld", ans % mod);
    return 0;
}
原文地址:https://www.cnblogs.com/Andy-park/p/13834351.html