Bishops

题意:

给定一个 $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;
}
View Code

 

posted @ 2017-06-15 16:52  lawyer'  阅读(282)  评论(0编辑  收藏  举报