P2051 [AHOI2009] 中国象棋(dp)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2051 [AHOI2009] 中国象棋(dp)相关的知识,希望对你有一定的参考价值。

P2051 [AHOI2009] 中国象棋(dp)

考虑按行递推。

显然对于前 i i i行 的答案,我们只需要知道前 i − 1 i-1 i1行 那些列没放,放了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 状态压缩+容斥

Luogu P2051 [AHOI2009]中国象棋 | dp

P2051 [AHOI2009]中国象棋[线性DP]

Luogu P2051 [AHOI2009]中国象棋

luogu P2051 [AHOI2009]中国象棋