您的位置:首页 > 其它

数学专项counting:UVa 10237

2013-11-08 23:27 645 查看
先将棋盘染成2种颜色,可以发现可以将棋盘的格子分成2种互不相关的类型。每种类型按对角线长度的奇偶性分类,同一类型的行列不能出现多个bishop。为了递推,可以将所有行按升序排列。

f1[i][j]表示对角线长度为奇数的第i行有j个bishop的方案数;

f2[i][j]表示对角线长度为偶数的第i行有j个bishop的方案数。

递推式为f[i][j]=f[i-1][j]+(c-j+1)*f[i-1][j-1],c为i行的格子数。

f1,f2均可预处理出来,然后结果即为sum{f1
[i]*f2
[k-i]|0<=i<=k}。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int maxn=40;
int n,k;
LL f1[maxn][maxn*maxn],f2[maxn][maxn*maxn];
void init()
{
memset(f1,0,sizeof(f1));
memset(f2,0,sizeof(f2));
f1[0][0]=1;
for(int i=1;i<=30;i++)
{
int c=(i%2)?i:i-1;
for(int j=0;j<=i;j++)
{
f1[i][j]=f1[i-1][j];
if(j) f1[i][j]+=(c-j+1)*f1[i-1][j-1];
}
}
f2[0][0]=1;
for(int i=1;i<=30;i++)
{
int c=(i%2)?i+1:i;
for(int j=0;j<=i;j++)
{
f2[i][j]=f2[i-1][j];
if(j) f2[i][j]+=(c-j+1)*f2[i-1][j-1];
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
init();
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(!n && !k) break;
LL ans=0;
for(int i=0;i<=k;i++)
{
//cout<<i<<" "<<k-i<<" "<<f1
[i]<<" "<<f2[n-1][k-i]<<endl;
ans+=f1
[i]*f2[n-1][k-i];
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: