zoukankan      html  css  js  c++  java
  • [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('
    ');
    		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;
    }
    
  • 相关阅读:
    代码抄袭检测系统的设计和实现(1)--需求分析和基础架构
    Protobuf C/C++实战笔记(1)
    自动构建Makefile(1)--C/C++编译流程&Makefile规则简介
    初识storm
    Ubuntu 16.04LTS安装Nginx
    redis内存监控与回收
    RabbitMQ交换机规则实例
    git合并分支上指定的commit
    git忽略掉文件权限检查
    git修改文件权限方式
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6900427.html
Copyright © 2011-2022 走看看