题意:
给定一个 $n*n$ 的国际棋盘,求问在上面放 $K$ 个象的方案数。
解法:
首先可以发现黑格和白格互不干扰,这样我们可以将黑格,白格分别求出。
考虑 $f(i,j)$ 表示坐标化后考虑长度为 $i,i-2,i-4,...$ 的 $y=x$ 斜线,放了 $j$ 个棋子的方案数。
这样有
$$f(i,j) = f(i-2,j) + 2(i-j+1)f(i-2,j-1) + (i-j+2)(i-j+1)f(i-2,j-2) , i<n$$
$$f(i,j) = f(i-2,j) + (i-j+1)f(i-2,j-1), j = n$$
$$ans = sum_{i=0}^K{f(n,i) cdot f(n-1,K-i)}$$
#include <bits/stdc++.h> #define LL unsigned long long const int N = 31; using namespace std; int n,K; LL f[N][N*N]; int main() { while(scanf("%d%d",&n,&K),n||K) { if(n==1) { cout<<1<<endl; continue; } memset(f,0,sizeof(f)); f[0][0] = 1; f[1][0] = 1; f[1][1] = 2; for(int i=2;i<=n;i++) for(int j=0;j<=i;j++) { f[i][j] = f[i-2][j]; if(j>=1) { if(i<n) { f[i][j] += f[i-2][j-1] * 2LL * (i-j+1LL); f[i][j] += f[i-2][j-2] * (i-j+2LL)*(i-j+1LL); } else f[i][j] += f[i-2][j-1] * (i-j+1LL); } } LL ans = 0; for(int i=0;i<=K;i++) ans += f[n][i] * f[n-1][K-i]; cout << ans << endl; } return 0; }