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) {;}
代码

 

posted @ 2017-09-19 17:10  拿叉插猹哈  阅读(141)  评论(0编辑  收藏  举报