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
我终于TM写对高精度了!!!
NOIP2014D2T3高精度写炸、2014海淀区赛高精度写炸、CCC2016高精度写炸、BJTSC2016二试高精度写炸。
总结起来是8个字:cnbb、mdzz。
考虑使用容斥原理,ans=g0-g1+g2-g3+----。其中gi表示至少有i个棋子放错的答案,则gi=C(k,i)*(n-i)!,k表示总障碍个数。
然后写高精度就行了。
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i;i=next[i]) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } typedef long long ll; const int maxn=410; struct bign { int len,s[maxn]; bign() {memset(s,0,sizeof(s));len=1;} void operator = (int b) { len=0;while(b) s[len++]=b%10,b/=10; } void clean() {while(len>1&&!s[len-1]) len--;} bign operator + (const bign& b) const { bign c;c.len=max(b.len,len)+1; rep(i,0,c.len-1) { c.s[i]+=s[i]+b.s[i]; c.s[i+1]+=c.s[i]/10; c.s[i]%=10; } c.clean();return c; } bign operator - (const bign& b) const { bign c;c.len=max(b.len,len); rep(i,0,c.len-1) { c.s[i]+=s[i]-b.s[i]; if(c.s[i]<0) c.s[i]+=10,c.s[i+1]--; } c.clean();return c; } bign operator * (const int b) const { bign c;c.len=len+5; int last=0; rep(i,0,c.len-1) { c.s[i]=s[i]*b+last; last=c.s[i]/10; c.s[i]%=10; } c.clean();return c; } bign operator * (const bign& b) const { bign c;c.len=len+b.len+2; rep(i,0,len-1) rep(j,0,b.len-1) c.s[i+j]+=s[i]*b.s[j]; rep(i,0,c.len-1) c.s[i+1]+=c.s[i]/10,c.s[i]%=10; c.clean();return c; } void print() {dwn(i,len-1,0) printf("%d",s[i]);puts("");} }; bign C[2][maxn],xp[maxn]; int main() { int n=read(),k=0; rep(i,1,n) rep(j,1,n) k+=read(); xp[0]=1;rep(i,1,n) xp[i]=xp[i-1]*i; int cur=0; rep(i,1,k) { cur^=1; C[cur][0]=1;C[cur][i]=1; rep(j,1,i-1) C[cur][j]=C[cur^1][j-1]+C[cur^1][j]; } bign ans=xp[n]; rep(i,1,k) { bign res=C[cur][i]*xp[n-i]; if(i&1) ans=ans-res; else ans=ans+res; } ans.print(); return 0; }