CF888D Almost Identity Permutations 题解
CF888D Almost Identity Permutations 题解
题目大意
给出 \(n, k\), 求满足下面条件的数组的个数
- 至少有 \(n - k\) 位的 \(a_i=i\) 即有 \(k\) 位错放。
解
题目大意可以理解为一个关于错放的问题。
但是本题有一个“至少”。
有 \(k\) 个数错排,又可以理解为在 \(n\) 里选择 \(k\) 个数错排,根据乘法原理可以得到答案应该是:\(C(n, k)\times f_k\),其中 \(f_k\) 表示 \(k\) 个数错排的方案数量。
当 \(k=1\) 时只有一种方案数。
答案就是 \(\sum_{i=2}^{k}(C(n,i)\times f_i)+1\) 其中的加 1 是加的 \(i=1\) 时的 1。
Code
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);std::cout.tie(0);
int n, k;
std::cin >> n >> k;
std::vector<std::vector<i64> > c(n + 1, std::vector<i64>(n + 1));
c[0][0] = c[1][0] = c[1][1] = 1;
for (int i = 2; i <= n; i++) {
c[i][0] = 1;
for (int j = 1; j <= i; j++) {
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]);
}
}
std::vector<i64> f(n + 1);
f[1] = 0, f[2] = 1;
for (int i = 3; i <= n; i++) {
f[i] = (i - 1) * (f[i - 1] + f[i - 2]);
}
i64 ans = 1;
for (int i = 2; i <= k; i++) {
ans += c[n][i] * f[i];
}
std::cout << ans << std::endl;
return 0;
}

浙公网安备 33010602011771号