【BZOJ4563】[Haoi2016]放棋子 错排+高精度
【BZOJ4563】[Haoi2016]放棋子
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
题解:傻题。
其实只需要读入n就行。因为障碍矩阵可以看成是一个1到n的排列,最后防棋子的位置也可以看成一个1到n的排列。所以答案就是错排的方案数。只需套用错排的经典公式:f[i]=(i-1)*(f[i-1]+f[i-2])。
然而答案不取模,所以用高精度即可。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int n; struct node { int l,v[110]; node() {memset(v,0,sizeof(v)),l=1;} node operator + (const node &a) const { node b; b.l=max(l,a.l); for(int i=1;i<=b.l;i++) b.v[i]+=v[i]+a.v[i],b.v[i+1]=b.v[i]/1000,b.v[i]%=1000; if(b.v[b.l+1]) b.l++; return b; } node operator * (const int &a) const { node b; b.l=l; for(int i=1;i<=l;i++) b.v[i]+=v[i]*a,b.v[i+1]=b.v[i]/1000,b.v[i]%=1000; if(b.v[b.l+1]) b.l++; return b; } }a,b,c; int main() { scanf("%d",&n); if(!n) { printf("0"); return 0; } int i; a.l=b.l=a.v[1]=1; for(i=1;i<n;i++) c=a,a=b,b=(c+b)*i; printf("%d",b.v[b.l]); for(i=b.l-1;i;i--) printf("%03d",b.v[i]); return 0; }
| 欢迎来原网站坐坐! >原文链接<