[BZOJ4563][Haoi2016]放棋子
[BZOJ4563][Haoi2016]放棋子
试题描述
给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少种方案。
输入
第一行一个N,接下来一个N*N的矩阵。N<=200,0表示没有障碍,1表示有障碍,输入格式参考样例
输出
一个整数,即合法的方案数。
输入示例
2 0 1 1 0
输出示例
1
数据规模及约定
见“输入”
题解
我们发现交换两行不会影响结果,于是任意一个合法的矩阵通过交换都能变成主对角线为 1 其余为 0 的矩阵。
然后对于第 i 行我们确定一个位置 Pi,满足 Pi ≠ i,求有多少种方案。这其实就是一个经典的错位排序问题。
我们考虑对于 Pn,令 Pn = x。接下来分情况讨论,若 Px = n,那么就是剩下的 n - 2 个数错位排序;若 Px ≠ n,那么如果把 n 想象成原来的 x,就是要确定 P1 到 Pn-1 的值,即一个 n - 1 个数的错位排序。由于 Pn 有 n - 1 种取法,得到递推式 F(n) = (F(n-1) + F(n-2)) * (n - 1).
写(贴)个高精度模板就好了。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
struct LL {
int len, A[510];
LL() { len = -1; }
LL(int x) {
A[1] = x; len = 1;
if(x) while(A[len] > 9) A[len+1] = A[len] / 10, A[len] %= 10, len++;
else len = -1;
}
LL operator = (const int& t) {
A[1] = t; len = 1;
if(t) while(A[len] > 9) A[len+1] = A[len] / 10, A[len] %= 10, len++;
else len = -1;
return *this;
}
LL operator + (const LL& t) const {
LL ans; ans.len = max(len, t.len);
for(int i = 1; i <= ans.len; i++) ans.A[i] = (i <= len ? A[i] : 0) + (i <= t.len ? t.A[i] : 0);
for(int i = 1; i < ans.len; i++) if(ans.A[i] > 9) ans.A[i+1] += ans.A[i] / 10, ans.A[i] %= 10;
while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++;
return ans;
}
LL operator += (const LL& t) {
*this = *this + t;
return *this;
}
LL operator + (const int& t) const {
LL ans; ans.len = max(len, 1);
for(int i = 1; i <= ans.len; i++) ans.A[i] = A[i]; ans.A[1] += t;
for(int i = 1; i < ans.len; i++) if(ans.A[i] > 9) ans.A[i+1] += ans.A[i] / 10, ans.A[i] %= 10;
while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++;
return ans;
}
LL operator += (const int& t) {
*this = *this + t;
return *this;
}
LL operator ++ () { // ++this;
*this = *this + 1;
return *this;
}
LL operator ++ (int x) { // this++;
*this = *this + 1;
return *this - 1;
}
LL operator - (const LL& t) const {
if(t.len < 0) return *this;
LL ans; ans.len = max(len, t.len);
for(int i = 1; i <= ans.len; i++) ans.A[i] = A[i] - t.A[i];
for(int i = 1; i < ans.len; i++) if(ans.A[i] < 0) {
int tmp = (-ans.A[i] + 9) / 10;
ans.A[i+1] -= tmp; ans.A[i] += tmp * 10;
}
while(!ans.A[ans.len]) ans.len--;
return ans;
}
LL operator -= (const LL& t) {
*this = *this - t;
return *this;
}
LL operator - (const int& t) const {
LL ans; ans.len = len;
for(int i = 1; i <= ans.len; i++) ans.A[i] = A[i]; ans.A[1] -= t;
for(int i = 1; i < ans.len; i++) if(ans.A[i] < 0) {
int tmp = (-ans.A[i] + 9) / 10;
ans.A[i+1] -= tmp; ans.A[i] += tmp * 10;
}
while(!ans.A[ans.len]) ans.len--;
return ans;
}
LL operator -= (const int& t) {
*this = *this - t;
return *this;
}
LL operator -- () { // --this;
*this = *this - 1;
return *this;
}
LL operator -- (int x) { // this--;
*this = *this - 1;
return *this + 1;
}
LL operator * (const LL& t) const {
LL ans; ans.len = len + t.len - 1;
if(len < 0 || t.len < 0) return ans.len = -1, ans;
for(int i = 1; i <= ans.len; i++) ans.A[i] = 0;
for(int i = 1; i <= len; i++)
for(int j = 1; j <= t.len; j++) ans.A[i+j-1] += A[i] * t.A[j];
for(int i = 1; i < ans.len; i++) if(ans.A[i] > 9) ans.A[i+1] += ans.A[i] / 10, ans.A[i] %= 10;
while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++;
return ans;
}
LL operator *= (const LL& t) {
*this = *this * t;
return *this;
}
LL operator * (const int& t) const {
LL ans = t;
return ans * (*this);
}
LL operator *= (const int& t) {
*this = *this * t;
return *this;
}
bool operator < (const LL& t) const {
if(len != t.len) return len < t.len;
for(int i = len; i > 0; i--) if(A[i] != t.A[i]) return A[i] < t.A[i];
return 0;
}
bool operator > (const LL& t) const {
if(len != t.len) return len > t.len;
for(int i = len; i > 0; i--) if(A[i] != t.A[i]) return A[i] > t.A[i];
return 0;
}
bool operator == (const LL& t) const {
if(len != t.len) return 0;
for(int i = len; i > 0; i--) if(A[i] != t.A[i]) return 0;
return 1;
}
bool operator != (const LL& t) const {
return !((*this) == t);
}
bool operator <= (const LL& t) const {
return *this < t || *this == t;
}
bool operator >= (const LL& t) const {
return *this > t || *this == t;
}
LL operator / (const LL& t) const {
LL ans, f = 0; ans.len = -1;
for(int i = 1; i <= len; i++) ans.A[i] = 0;
for(int i = len; i > 0; i--) {
f = f * 10 + A[i];
while(f >= t) {
f -= t; ans.A[i]++;
ans.len = max(ans.len, i);
}
}
return ans;
}
LL operator /= (const LL& t) {
*this = *this / t;
return *this;
}
LL operator / (const int& t) const {
LL ans; int f = 0; ans.len = -1;
for(int i = 1; i <= len; i++) ans.A[i] = 0;
for(int i = len; i > 0; i--) {
f = f * 10 + A[i];
while(f >= t) {
f -= t; ans.A[i]++;
ans.len = max(ans.len, i);
}
}
return ans;
}
LL operator /= (const int& t) {
*this = *this / t;
return *this;
}
void print() {
if(len < 0){ putchar('0'); return ; }
for(int i = len; i > 0; i--) putchar(A[i] + '0'); putchar('\n');
return ;
}
};
#define maxn 210
LL f[maxn];
int main() {
int n = read();
for(int i = 1; i <= n * n; i++) read();
f[1] = 0; f[2] = 1;
for(int i = 3; i <= n; i++) f[i] = (f[i-2] + f[i-1]) * (i - 1);
f[n].print();
return 0;
}

浙公网安备 33010602011771号