/*
dp预处理再加组合数
题意:在n*m的格子上有一个棋子,它的移动规则(设初始点为(x,y)):可以移到(x+1,y),(x+2,y),(x-1,y),(x-2,y),(x,y+1),(x,y+2),(x,y-1),(x,y-2)
解法:n^2 dp预处理,再组合数求解.
先dp预处理出横向和纵向走i步的总的方法数,则最后答案为sigma(C(k,i)*e[i]*f[i])
注意特判n=1,m=1的情况,这时候应当输出0
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 1111
#define mod 9999991
int dp1[maxn][maxn];
int e[maxn];
int dp2[maxn][maxn];
int f[maxn];
int cb[maxn][maxn];
#define LL long long
int calc(int n, int k)
{
if (!k || n == k)
return 1;
if (~cb[n][k])
return cb[n][k];
return cb[n][k] = (calc(n - 1, k - 1) + calc(n - 1, k)) % mod;
}
int main()
{
int T;
scanf("%d",&T);
int kase=1;
memset(cb,-1,sizeof(cb));
while(T--)
{
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
memset(e,0,sizeof(e));
memset(f,0,sizeof(f));
int n,m,k,x0,y0;
scanf("%d%d%d%d%d",&n,&m,&k,&x0,&y0);
if(n==1&&m==1)
{
printf("Case #%d:\n0\n",kase++);
continue;
}
dp1[0][x0]=1;
for(int i=1;i<=k;i++)
{
for(int j=1;j<=n;j++)
{
if(j+1<=n) dp1[i][j]=(dp1[i][j]+dp1[i-1][j+1])%mod;
if(j+2<=n) dp1[i][j]=(dp1[i][j]+dp1[i-1][j+2])%mod;
if(j-1>=1) dp1[i][j]=(dp1[i][j]+dp1[i-1][j-1])%mod;
if(j-2>=1) dp1[i][j]=(dp1[i][j]+dp1[i-1][j-2])%mod;
}
}
for(int i=0;i<=k;i++)
{
for(int j=1;j<=n;j++)
{
e[i]=(e[i]+dp1[i][j])%mod;
}
}
dp2[0][y0]=1;
for(int i=1;i<=k;i++)
{
for(int j=1;j<=m;j++)
{
if(j+1<=m) dp2[i][j]=(dp2[i][j]+dp2[i-1][j+1])%mod;
if(j+2<=m) dp2[i][j]=(dp2[i][j]+dp2[i-1][j+2])%mod;
if(j-1>=1) dp2[i][j]=(dp2[i][j]+dp2[i-1][j-1])%mod;
if(j-2>=1) dp2[i][j]=(dp2[i][j]+dp2[i-1][j-2])%mod;
}
}
for(int i=0;i<=k;i++)
{
for(int j=1;j<=m;j++)
{
f[i]=(f[i]+dp2[i][j])%mod;
}
}
LL ans=0;
for(int i=0;i<=k;i++)
{
//printf("%d %d\n",e[i],f[i]);
LL v=calc(k,i);
v=v*e[i]%mod;
v=v*f[k-i]%mod;
ans=(ans+v)%mod;
}
//printf("%d %d\n",dp1[2][1],dp2[2][1]);
printf("Case #%d:\n%lld\n",kase++,(ans+mod)%mod);
}
return 0;
}
HDU 4832 Chess
最新推荐文章于 2021-01-19 20:52:36 发布