BZOJ4563:[HAOI2016]放棋子——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=4563

给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少种方案。

假设最开始棋子都放在障碍上,然后将所有行压成一行,那么下面的问题就是有多少种方法使得棋子不放在自己原来的位置上并且不能与别的棋子重合?

这就是一个错排问题了,高精即可。

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct Bignum{//必须定义在main之外
int a[N],len;
Bignum(){
memset(a,,sizeof(a));len=;
}
void print(){
for(int i=len-;i>=;i--)putchar(a[i]+'');
putchar('\n');
}
Bignum operator +(const Bignum &b)const{
Bignum ans;ans.len=len;
for(int i=;i<ans.len;i++)ans.a[i]=a[i];
for(int i=;i<ans.len;i++){
ans.a[i]+=b.a[i];
if(ans.a[i]>){
ans.a[i]-=;ans.a[i+]++;
if(i+==ans.len)ans.len++;
}
}
if(ans.len<b.len){
for(int i=ans.len;i<b.len;i++)ans.a[i]=b.a[i];
ans.len=b.len;
}
return ans;
}
Bignum operator *(const int &b)const{
Bignum ans;ans.len=len;
for(int i=;i<ans.len;i++)ans.a[i]=a[i]*b;
for(int i=;i<ans.len;i++){
if(ans.a[i]>){
ans.a[i+]+=ans.a[i]/;ans.a[i]%=;
if(i+==ans.len)ans.len++;
}
}
return ans;
}
}d1,d2;
int n;
int main(){
n=read();
if(n==){puts("");return ;}
if(n==){puts("");return ;}
d1.a[]=;d1.len=;
d2.a[]=;d2.len=;
for(int i=;i<=n;i++){
Bignum ans=(d2+d1)*(i-);
swap(d1,d2);swap(d2,ans);
}
d2.print();
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

上一篇:洛谷P3182 [HAOI2016]放棋子


下一篇:洛谷 P3182 [HAOI2016]放棋子(高精度,错排问题)