题目链接:传送门
题目说了
每行有一个障碍
两个障碍不在同一行也不在同一列
那障碍放哪里就没关系了
矩阵都不用输入
或者这样理解:
交换矩阵的某两行对答案是没有影响的
那么我们把所有障碍移到对角线处
那么剩下的棋子就是做一个错排
当然还有高精
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdio>
#include <iomanip>
using namespace std;
namespace BigInteger {
#define
struct Big_integer {
int d[maxn], len;
void clean() {while(len > 1 and !d[len - 1]) len--;}
Big_integer() {memset(d, 0, sizeof d); len = 1;}
Big_integer(int num) {*this = num;}
Big_integer(char* num) {*this = num;}
Big_integer operator = (const char *num) {
memset(d, 0, sizeof d);
len = strlen(num);
for (int i = 0; i < len; i++) d[i] = num[len - 1 - i] - '0';
clean();
return *this;
}
Big_integer operator = (int num) {
char s[10005];
sprintf(s, "%d", num);
*this = s;
return *this;
}
Big_integer operator + (const Big_integer &b) {
Big_integer c = *this; int i;
for (i = 0; i < b.len; i++) {
c.d[i] += b.d[i];
if (c.d[i] > 9) c.d[i] %= 10, c.d[i + 1]++;
}
while (c.d[i] > 9) c.d[i++] %= 10, c.d[i]++;
c.len = max(len, b.len);
if (c.d[i] and c.len <= i) c.len = i + 1;
return c;
}
Big_integer operator * (const Big_integer &b) const {
int i, j; Big_integer c;
c.len = len + b.len;
for (j = 0; j < b.len; j++)
for (i = 0; i < len; i++)
c.d[i + j] += d[i] * b.d[j];
for (i = 0; i < c.len - 1; i++) {
c.d[i + 1] += c.d[i] / 10;
c.d[i] %= 10;
}
c.clean();
return c;
}
string str() const {
char s[maxn];
for (int i = 0; i < len; i++) s[len - 1 - i] = d[i] + '0';
return s;
}
};
istream& operator >> (istream &in, Big_integer &x) {
string s;
in >> s;
x = s.c_str();
return in;
}
ostream& operator << (ostream &out, const Big_integer &x) {
out << x.str();
return out;
}
}
using namespace BigInteger;
Big_integer f[201]; int n;
int main(int argc, char const *argv[]) {
cin >> n; f[1] = 0; f[2] = 1;
for (int i = 3; i <= n; i++) f[i] = (f[i - 1] + f[i - 2]) * (i - 1);
cout << f[n] << endl;
}