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

posted @ 2022-02-09 16:09  落花月朦胧  阅读(75)  评论(0)    收藏  举报