【BZOJ4563】[Haoi2016]放棋子 錯排+高精度
阿新 • • 發佈:2017-11-19
高精 esc 表示 opera truct pre -- 答案 string
0 1
1 0
【BZOJ4563】[Haoi2016]放棋子
Description
給你一個N*N的矩陣,每行有一個障礙,數據保證任意兩個障礙不在同一行,任意兩個障礙不在同一列,要求你在這個矩陣上放N枚棋子(障礙的位置不能放棋子),要求你放N個棋子也滿足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少種方案。Input
第一行一個N,接下來一個N*N的矩陣。N<=200,0表示沒有障礙,1表示有障礙,輸入格式參考樣例Output
一個整數,即合法的方案數。Sample Input
20 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; }
【BZOJ4563】[Haoi2016]放棋子 錯排+高精度