目录
牛客_分解因数(简单模拟)
解析代码
该题为经典的错排问题
用A、B、C……表示写着n位友人名字的信封,a、b、c……表示n份相应的写好的信纸。把错装的总数为记作 D(n)。假设把a错装进B里了,包含着这个错误的一切错装法分两类:
- b装入A里,这时每种错装的其余部分都与A、B、a、b无关,应有D(n-2)种错装法。
- b装入A、B之外的一个信封,这时的装信工作实际是把(除a之外的)n-1份信纸b、c……装入(除B以外 的)n-1个信封A、C……,显然这时装错的方法有D(n-1)种。
总之在a装入B的错误之下,共有错装法D(n-2)+D(n-1)种。 a装入C,装入D……的n-2种错误之下,同样都有D(n-1)+D(n-2)种错装法,因此D(n)=(n-1)[D(n-1)+D(n- 2)]
所以D(n) = (n-1) [D(n-2) + D(n-1)] 。特殊的,D(1) = 0, D(2) = 1.
错排的递推公式是:D(n) = (n - 1) [D(n - 2) + D(n - 1)],也就是n - 1倍的前两项和。公式推导可以参考百度百科。 通过这个递推公式可以得到在总数为n的时候,错排的可能性一共有多少种。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<long long> dp(21, 0);
dp[2] = 1;
for(int i = 3; i < 21; ++i)
{
dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]);
}
int n = 0;
while(cin >> n)
{
cout << dp[n] << endl;
}
return 0;
}