📅  最后修改于: 2023-12-03 15:28:49.045000             🧑  作者: Mango
在一个长 $n(n \leq 10^7)$ 的序列中,第 $i$ 个元素的取值范围是 $[1, m](m \leq 10^4)$,某些元素有固定的取值,已知这些固定值,请你求出完整序列的方案数。
第一行包含三个整数 $n, m, k$,分别表示序列的长度,元素的取值范围和已知固定值的数量。
接下来 $k$ 行,每行包含两个整数 $pos, val$ 表示序列中第 $pos$ 个元素的值为 $val$。
输出一个整数,表示完整序列的方案数对 $10^9 + 7$ 取模的结果。
$1 \leq n, m \leq 10^4$ $1 \leq k \leq n$
温馨提示:本题的输出可能很大,请使用 64 位整数型。
可以使用动态规划来计算方案数。设 $f_i$ 表示考虑到第 $i$ 个位置时的方案数,则有:
$$ f_i=\begin{cases} 1, &(i\leq k) \ 0, &(val_{pos_i}\neq 0 \land val_{pos_i}\neq a_i) \ f_{i-1}, &(a_i=0) \ f_{i-1}-f_{pos_i-1}\times (m-1), &(pos_i<i\land a_i=0) \ \end{cases} $$
其中 $val_i$ 表示已知固定值的取值,$pos_i$ 表示已知固定值的位置。
最终答案为 $f_n$。
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int MOD = 1e9 + 7;
const int N = 10010;
int n, m, k;
int val[N], pos[N];
LL f[N], s[N];
int main()
{
cin >> n >> m >> k;
memset(val, -1, sizeof val);
for (int i = 0; i < k; i ++ )
{
int x, y;
cin >> x >> y;
val[x - 1] = y - 1, pos[x - 1] = i;
}
f[0] = 1;
s[0] = 1;
for (int i = 1; i <= n; i ++ )
{
if (~val[i - 1] && val[i - 1] != i - 1) f[i] = 0;
else if (~val[i - 1] && val[i - 1] == i - 1) f[i] = f[i - 1];
else if (pos[i - 1] == 0) f[i] = f[i - 1] * m % MOD;
else
{
f[i] = (f[i - 1] - s[pos[i - 1] - 1] * (m - 1) % MOD) % MOD;
f[i] += MOD, f[i] %= MOD;
}
s[i] = (s[i - 1] + f[i]) % MOD;
}
cout << f[n] << endl;
return 0;
}
时间复杂度:$O(n)$