P3182 [HAOI2016]放棋子
P3182 [HAOI2016]放棋子
题目描述
给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少种方案。
输入输出格式
输入格式:
第一行一个N,接下来一个N*N的矩阵。N<=200,0表示没有障碍,1表示有障碍,输入格式参考样例
输出格式:
一个整数,即合法的方案数。
输入输出样例
输入样例#1:
2 0 1 1 0
输出样例#1:
代码
1
每一行和每一列的1是互补影响的
所以对于每一个n 方案数是一定的
如果我们把第i行的1 放到第i个位置
也就是 第i行的第i个位置不能放棋子
就是一个错排问题
2000的数据 要写高精
1 /* 2 压位高精 3 */ 4 #include <cctype> 5 #include <cstdio> 6 #include <cstring> 7 8 const int p=4; 9 const int MAXN=5010; 10 const int mod=10000; 11 const int MAXM=10010; 12 13 int n,ans,tot; 14 15 int map[MAXN][MAXN],a[MAXM],b[MAXM],c[MAXM]; 16 17 inline void read(int&x) { 18 int f=1;register char c=getchar(); 19 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 20 for(;isdigit(c);x=x*10+c-48,c=getchar()); 21 x=x*f; 22 } 23 24 inline void mul(int x) { 25 c[0]=b[0]+1; 26 for(int i=1;i<=c[0];++i) c[i]=x*b[i]; 27 for(int i=1;i<=c[0];++i) { 28 if(i==c[0]&&c[i]>mod) ++c[0]; 29 c[i+1]+=c[i]/mod; 30 c[i]%=mod; 31 } 32 while(c[0]&&!c[c[0]]) --c[0]; 33 for(int i=1;i<=c[0];++i) b[i]=c[i]; 34 b[0]=c[0]; 35 memset(c,0,sizeof c); 36 } 37 38 inline void plus() { 39 c[0]=b[0]+1; 40 for(int i=1;i<=c[0];++i) { 41 c[i]+=a[i]+b[i]; 42 c[i+1]+=c[i]/mod; 43 c[i]%=mod; 44 } 45 while(c[0]>0&&!c[c[0]]) --c[0]; 46 for(int i=1;i<=b[0];++i) a[i]=b[i]; 47 a[0]=b[0]; 48 for(int i=1;i<=c[0];++i) b[i]=c[i]; 49 b[0]=c[0]; 50 memset(c,0,sizeof c); 51 } 52 53 int hh() { 54 freopen("chess_2016.in","r",stdin); 55 freopen("chess_2016.out","w",stdout); 56 read(n); 57 for(int i=1;i<=n;++i) 58 for(int j=1;j<=n;++j) 59 read(map[i][j]); 60 a[0]=1;b[0]=1; 61 a[a[0]]=1;b[b[0]]=2; 62 if(n==2) {printf("1\n");return 0;} 63 if(n==3) {printf("2\n");return 0;} 64 for(int i=4;i<=n;++i) plus(),mul(i-1); 65 printf("%d",b[b[0]]); 66 for(int i=b[0]-1;i>=1;--i) printf("%0*d",p,b[i]); 67 return 0; 68 } 69 70 int sb=hh(); 71 int main(int argc,char**argv) {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现