CF1838E Count Supersequences 题解
思路
诈骗题。首先发现 \(a_i\) 其实没有任何用,所以可以令所有 \(a_i = 1\)。设 \(f(i)\) 代表构造 \(b\) 的方案数,使得 \(b\) 中恰好有 \(i\) 个 \(1\)。可得:
\[f(i) = \binom{m}{i} \cdot (k - 1) ^ {m - i}
\]
代表在 \(m\) 中选 \(i\) 个位置放 \(1\),剩下 \(m - i\) 个位置不能填 \(1\),又因为 \(a_i \in [1, k]\),所以有 \(k - 1\) 中选法。那所以答案就是 \(\sum \limits_{i = n}^m f(i)\),可是 \(m \le 10^9\)。
考虑正难则反。因为总方案数显然为 \(k^m\),所以合法方案数就为 \(k^m - \sum \limits_{i = 1}^{n - 1} f(i)\),就做完了。
因为 \(m\) 很大,\(\binom{m}{i}\) 不能用阶乘预处理,所以用递推:
\[\binom{m}{i} = \binom{m}{i - 1} \cdot \displaystyle \frac{n - i + 1}{i}
\]
这样就结束了。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5, mod = 1e9 + 7;
int t, n, m, k;
int a[N], f[N], c[N];
int fastPow(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
void solve()
{
scanf("%lld%lld%lld", &n, &m, &k);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
int c = 1, ans = fastPow(k, m);
ans = ((ans - fastPow(k - 1, m)) % mod + mod) % mod;
for (int i = 1; i < n; i++)
{
c = (c * (m - i + 1) % mod) * fastPow(i, mod - 2) % mod;
f[i] = c * fastPow(k - 1, m - i) % mod;
ans = ((ans - f[i]) % mod + mod) % mod;
}
printf("%lld\n", ans);
}
signed main()
{
scanf("%lld", &t);
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号