Luogu P1595 信封问题

(large{题目链接})
(\)

题意:

某人写了(n)封信和(n)个信封,如果所有的信都装错了信封。求所有信都装错信封共有多少种不同情况。

思路:

1.依据递推公式:(D_n = (n-1) imes (D_{n-1} +D_{n-2}))
2.学习二项式反演发现这题也可以用这个做。
首先二项式反演的公式是:(f_{n}=sum limits^{n}_{i=0}left( -1 ight) ^{i}egin{pmatrix} n \ i end{pmatrix}g_{i} Leftrightarrow g_{n}=sum limits^{n}_{i=0}left( -1 ight) ^{i}egin{pmatrix} n \ i end{pmatrix}f_{i})
更常用的式子是(f_{n}=sum limits^{n}_{i=0}egin{pmatrix} n \ i end{pmatrix}g_{i}Leftrightarrow g_{n}=sum limits^{n}_{i=0}left( -1 ight) ^{n-i}egin{pmatrix} n \ i end{pmatrix}f_{i})
回归这个题,我们知道(n)个信的排列的方案数是(n!)
(f_i)表示有(i)恰好有(i)个位置改变的排列个数,那么(n)个的排列总数就是(i = 0,1,...,n-1,n)的和,即(n! = sum limits^{n}_{i=0}egin{pmatrix} n \ i end{pmatrix}f_{i}),观察这个式子,与刚刚的反演式子很相似,这里的(n!)就是(g_n)
那么利用二项式反演公式可以得到:

[f_n = sum limits^{n}_{i=0}left( -1 ight) ^{i+n}egin{pmatrix} n \ i end{pmatrix}f_{i}]

[=n!sum limits^{n}_{i=0}dfrac {left( -1 ight) ^{i}}{i!} ]

由于没有逆元,所以把(n!)提进去。

代码:

#include <bits/stdc++.h>

typedef long long ll;

int main() {
	ll fac[23];
	fac[0] = fac[1] = 1;
	for (int i = 2; i <= 20; ++i) fac[i] = fac[i - 1] * i;
	int n;
	std::cin >> n;
	ll ans = 0;
	for (int i = 0; i <= n; ++i) ans += (i & 1) ? -(fac[n] / fac[i]) : fac[n] / fac[i];
	std::cout << ans;
	return 0;
} 
原文地址:https://www.cnblogs.com/Miraclys/p/12777320.html