bzoj4563: [Haoi2016]放棋子(错排+高精)
4563: [Haoi2016]放棋子
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 387 Solved: 247
[Submit][Status][Discuss]
Description
给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在
这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子
的限制,求有多少种方案。
Input
第一行一个N,接下来一个N*N的矩阵。N<=200,0表示没有障碍,1表示有障碍,输入格式参考样例
Output
一个整数,即合法的方案数。
Sample Input
2
0 1
1 0
0 1
1 0
Sample Output
1
/* 每一行每一列只能放1个求方案数 转化为错排问题 练习高精压位 压9位。。。 */ #include <iostream> #include <cstdio> #include<iomanip> #define N 2001 #define mod 1000000000 #define _ 9 #define ll long long using namespace std; ll n; struct num { ll d[N],w; /* void print() { for (ll i=w;i>=1;i--) cout<<d[i]; printf("\n"); }*/ }D[N],id; num operator +(num p1,num p2) { num ret=id; ll g=0; if (p1.w<p2.w) swap(p1,p2); ret.w=p1.w; for (ll i=1;i<=p1.w;i++) { ret.d[i]=(p1.d[i]+p2.d[i]+g)%mod; g=(p1.d[i]+p2.d[i]+g)/mod; } while(g) ret.d[++ret.w]=g%mod , g/=mod; return ret; } num mul(num p1,ll p2) { num ret=id; ret.w=p1.w; ll g=0; for (ll i=1;i<=p1.w;i++) { ret.d[i]=(p1.d[i]*p2+g)%mod; g=(p1.d[i]*p2+g)/mod; } while(g) ret.d[++ret.w]=g%mod,g/=mod; return ret; } ostream& operator << (ostream &os,num x) { ll i; os<<x.d[x.w]; for(i=x.w-1;i;i--) os<<setfill('0')<<setw(_)<<x.d[i]; return os; } int main() { scanf("%d",&n); if (n == 1) { puts("0"); return 0; } D[1]=id; D[2].w=D[2].d[1]=1; for (ll i=3;i<=n;i++) D[i] = mul((D[i-1]+D[i-2]),i-1); cout<<D[n]; return 0; }
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。