题解 - [UVa 10497] Sweet Child Makes Trouble

题目链接

原始题面

Children are always sweet but they can sometimes make you feel bitter. In this problem, you will see how Tintin, a five year’s old boy, creates trouble for his parents. Tintin is a joyful boy and is always busy in doing something. But what he does is not always pleasant for his parents. He likes most to play with household things like his father’s wristwatch or his mother’s comb. After his playing he places it in some other place. Tintin is very intelligent and a boy with a very sharp memory. To make things worse for his parents, he never returns the things he has taken for playing to their original places

Think about a morning when Tintin has managed to ‘steal’ three household objects. Now, in how many ways he can place those things such that nothing is placed in their original place. Tintin does not like to give his parents that much trouble. So, he does not leave anything in a completely new place; he merely permutes the objects

Input

There will be several test cases. Each will have a positive integer less than or equal to 800 indicating the number of things Tintin has taken for playing. Each integer will be in a line by itself. The input is terminated by a ‘-1’ (minus one) in a single line, which should not be processed

Output

For each test case print an integer indicating in how many ways Tintin can rearrange the things he has taken

Sample Input

1
2
3
4
2
3
4
-1

Sample Output

1
2
3
1
2
9

题意简述

\(n\) 个元素的错排数

解题思路

板子题,唯一要注意的就是要用高精

\(D(n)\)\(n\) 个元素的错排数,则

\[ D(n)=\begin{cases} 0,&n=1\\ 1,&n=2\\ (n-1)(D(n-1)+D(n-2)),&n>2 \end{cases} \]

代码参考

Show code

UVA_10497view raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
* @Author: Tifa
* @Description: From <https://github.com/Tiphereth-A/CP-archives>
* !!! ATTENEION: All the context below is licensed under a
* GNU Affero General Public License, Version 3.
* See <https://www.gnu.org/licenses/agpl-3.0.txt>.
*/
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
const int N = 2e4 + 10;
struct BigInt {
int len, s[N];
BigInt() {
memset(s, 0, sizeof(s));
len = 1;
}
BigInt(int num) { *this = num; }
BigInt(const char *num) { *this = num; }
BigInt operator=(int num) {
char s[N];
sprintf(s, "%d", num);
*this = s;
return *this;
}
string str() const {
string res = "";
for (int i = 0; i < len; i++) res = (char)(s[i] + '0') + res;
if (res == "") res = "0";
return res;
}
void clean() {
while (len > 1 && !s[len - 1]) len--;
}
BigInt operator=(const char *num) {
len = strlen(num);
for (int i = 0; i < len; i++) s[i] = num[len - i - 1] - '0';
return *this;
}
BigInt operator+(const BigInt &b) const {
BigInt c;
c.len = 0;
for (int i = 0, g = 0; g || i < max(len, b.len); i++) {
int x = g;
if (i < len) x += s[i];
if (i < b.len) x += b.s[i];
c.s[c.len++] = x % 10;
g = x / 10;
}
return c;
}
BigInt operator*(const BigInt &b) {
BigInt c;
c.len = len + b.len;
for (int i = 0; i < len; i++)
for (int j = 0; j < b.len; j++) c.s[i + j] += s[i] * b.s[j];
for (int i = 0; i < c.len - 1; i++) {
c.s[i + 1] += c.s[i] / 10;
c.s[i] %= 10;
}
c.clean();
return c;
}
BigInt operator-(const BigInt &b) {
BigInt c;
c.len = 0;
for (int i = 0, g = 0; i < len; i++) {
int x = s[i] - g;
if (i < b.len) x -= b.s[i];
if (x >= 0) g = 0;
else {
g = 1;
x += 10;
}
c.s[c.len++] = x;
}
c.clean();
return c;
}
};
ostream &operator<<(ostream &out, const BigInt &x) {
out << x.str();
return out;
}
BigInt ans[805];
int main() {
int n;
ans[1] = 0;
ans[2] = 1;
for (int i = 3; i <= 800; ++i)
ans[i] = BigInt(i - 1) * (ans[i - 1] + ans[i - 2]);
while (cin >> n && ~n) cout << ans[n] << endl;
return 0;
}