请用c++编写程序解决以下问题:有一条长度为n的路,要求在路上种树,1~n的每个位置最多只能种一棵树,开始路上没有任何树,有q次计划,每次计划形如第x个位置必须不能种树,任意两棵树之间的距离不小于k。 输出答案对998244353取模的结果。
时间: 2024-02-13 22:00:17 浏览: 61
好的,以下是C++代码实现:
```c++
#include <iostream>
#include <vector>
using namespace std;
const int MOD = 998244353;
int main() {
int n, q, k;
cin >> n >> q >> k;
vector<int> dp(n + 1), sum(n + 1);
dp[0] = sum[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = sum[i - 1];
if (i - k >= 2) {
dp[i] = (dp[i] + sum[i - k - 1] - dp[i - k - 1] + MOD) % MOD;
}
sum[i] = (sum[i - 1] + dp[i]) % MOD;
}
for (int i = 0; i < q; i++) {
int x;
cin >> x;
if (x == 1 || x == n) {
cout << 0 << endl;
} else {
cout << (sum[x - 1] * dp[n - x] % MOD) << endl;
}
}
return 0;
}
```
思路解析:
本题可以用动态规划的思想来解决。设 $dp_i$ 表示种树到第 $i$ 个位置的方案数,$sum_i$ 表示前 $i$ 个位置的方案数之和。则有:
$$dp_i = \begin{cases} 1, & i = 0 \\ sum_{i-1}, & i = 1 \\ sum_{i-1} - dp_{i-k-1} + sum_{i-k-1}, & i \ge 2 \end{cases}$$
其中,第三个转移方程的含义是:当种树到第 $i$ 个位置时,它可能是从第 $i-1$ 个位置移动而来,也可能是从第 $i-k-1$ 个位置移动而来(因为任意两棵树之间的距离不小于 $k$)。但是,如果从第 $i-k-1$ 个位置移动而来的话,第 $i-k$ 个位置必须不种树,因此要减去 $dp_{i-k-1}$,同时加上 $sum_{i-k-1}$,表示第 $i-k$ 个位置不种树的方案数。
最后,我们可以通过 $dp$ 数组和 $sum$ 数组来计算每次计划的答案。设第 $x$ 个位置不能种树,则可以将方案分成两部分:前 $x-1$ 个位置种树,方案数为 $sum_{x-1}$;后 $n-x$ 个位置种树,方案数为 $dp_{n-x}$。因此,答案为 $sum_{x-1} \times dp_{n-x}$。注意特判 $x=1$ 和 $x=n$ 的情况,这时答案为 $0$。
阅读全文