P2051 [AHOI2009] 中国象棋(dp)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2051 [AHOI2009] 中国象棋(dp)相关的知识,希望对你有一定的参考价值。
P2051 [AHOI2009] 中国象棋(dp)
考虑按行递推。
显然对于前 i i i行 的答案,我们只需要知道前 i − 1 i-1 i−1行 那些列没放,放了1个,放了2个的情况。
因此这样设状态 d p ( i , j , k ) dp(i,j,k) dp(i,j,k) 表示前 i i i行有 j j j列放了一个, k k k列放了两个。
然后枚举当前行 放 0 , 1 , 2 0,1,2 0,1,2个进行递推即可。
时间复杂度: O ( n m 2 ) O(nm^2) O(nm2)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstring>
#define mod 9999973
#define int long long
#define R register
using namespace std;
inline void in(int &x)
int f=1;x=0;char s=getchar();
while(!isdigit(s))if(s=='-')f=-1;s=getchar();
while(isdigit(s))x=x*10+s-'0';s=getchar();
x*=f;
int n,m,ans;
int f[108][108][108];
inline int C(int x)
return ((x*(x-1))/2)%mod;
signed main()
in(n),in(m);
f[0][0][0]=1;
for(R int i=1;i<=n;i++)
for(R int j=0;j<=m;j++)
for(R int k=0;k<=m-j;k++)
f[i][j][k]=f[i-1][j][k];
if(k>=1)(f[i][j][k]+=f[i-1][j+1][k-1]*(j+1));
if(j>=1)(f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1));
if(k>=2)(f[i][j][k]+=f[i-1][j+2][k-2]*(((j+2)*(j+1))/2));
if(k>=1)(f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1));
if(j>=2)(f[i][j][k]+=f[i-1][j-2][k]*C(m-j-k+2));
f[i][j][k]%=mod;
for(R int i=0;i<=m;i++)
for(R int j=0;i+j<=m;j++)
(ans+=f[n][i][j])%=mod;
printf("%lld",(ans+mod)%mod);
以上是关于P2051 [AHOI2009] 中国象棋(dp)的主要内容,如果未能解决你的问题,请参考以下文章
Luogu P2051 [AHOI2009]中国象棋 //DP
luogu P2051 [AHOI2009]中国象棋 dp 状态压缩+容斥