2486 - J
象 是国际象棋中的一种棋子,象的走法只可斜走,格数不限,但不可转向。
白格的象只可以在白格出现,黑格的象只可以在黑格出现。
现在给你一个n*n的棋盘,放置恰好k只象,且每只象不在其他象的攻击范围之内,输出方案数对(1e9+7)取余的值。
Input
多组数据,每组输入n,k (n<100,k<10000)
<br />
Output
输出方案数%1000000007。
Examples
Input
2 1 2 2 6 8
Output
4 4 12944
Hint
First sample: 22的棋盘上放置一枚象,有四种方案:
10 01 00 00
00 00 10 01
Second sample: 22的棋盘上放置两枚象,有如下四种方案:
11 10 01 00
00 10 01 11
Solution C++
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; #define mod 1000000007 #define N 101 int b[N],w[N]; int n,k; LL R_b[N][N*N],R_w[N][N*N]; void cal(int c[],LL R[][N*N]){ memset(R,0,sizeof(R)); for(int i=0;i<=n;i++) R[i][0]=1; for(int i=1;i<=n;i++) for(int j=1;j<=c[i];j++) R[i][j]=(R[i-1][j]+R[i-1][j-1]*(c[i]-(j-1)))%mod; } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(scanf("%d%d",&n,&k)!=EOF){ if(n==0 && k==0) break; memset(b,0,sizeof(b)),memset(w,0,sizeof(w)); memset(R_w,0,sizeof(R_w)),memset(R_b,0,sizeof(R_b)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if((i+j)&1) w[(i+j)>>1]++; else b[(i+j)>>1]++; sort(w+1,w+n),sort(b+1,b+n+1); cal(w,R_w),cal(b,R_b); LL ans=0; for(int i=0;i<=k;i++) ans=(ans+R_w[n-1][i]*R_b[n][k-i])%mod; printf("%lld\n",ans); } return 0; }
Hint
First sample: 22的棋盘上放置一枚象,有四种方案:
10 01 00 00
00 00 10 01
Second sample: 22的棋盘上放置两枚象,有如下四种方案:
11 10 01 00
00 10 01 11