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;
}