HDU - 6415

题目链接:HDU - 6415


我们假设是从大到小放,那么我们可以发现当前放的时候,必须在已经放过的一行或者一列放。

那么就成了一个dp问题了,dp[i][j][k]前 i 个数字,已经放了 j 行,k 列的方案数。

因为每个数只和之和前一个数字有关,所以可以空间优化。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=85;
int n,m,mod,dp[2][N][N],now;
inline void add(int &x,int y){x+=y; if(x>=mod) x-=mod;}
inline void solve(){
	cin>>n>>m>>mod; memset(dp,0,sizeof dp); now=0;// dp[0][0][0]=1%mod;
	dp[0][1][1]=n*m%mod;
	for(int i=2;i<=n*m;i++){
		now^=1;	memset(dp[now],0,sizeof dp[now]);
		for(int j=1;j<=n;j++){
			for(int k=1;k<=m;k++)	if(j*k>=i){
				add(dp[now][j][k],1LL*dp[now^1][j][k]*(j*k-i+1)%mod);
				add(dp[now][j][k],1LL*dp[now^1][j-1][k]*(n+1-j)%mod*k%mod);
				add(dp[now][j][k],1LL*dp[now^1][j][k-1]*(m+1-k)%mod*j%mod);
			}
		}
	}
	printf("%d\n",dp[now][n][m]);
}
signed main(){
	int T; cin>>T; while(T--) solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/107711728
hdu
今日推荐