question
这题题目全是图,就不贴了(感觉好多题都是图。。。)
Solution
正解DP
我们设表示放到第i个鞍点,其中的最大值为j的方案数。
我们使放置的鞍点的大小严格不下降(这样计算较方便)
而后,我们将推到下一个: 这里的n<m
转移方程很容易得到:
其中表示,M[i][j]表示。
最后我们就用容斥来搞一搞就可以了。
code
#include<cstdio>
#define N 2010
#define ll long long
using namespace std;
ll jc[N],yh[N][N],M[11][N*N],f[11][N],ans=0;
int n,m,K,mo;
void ycl()
{
if (n>m) n=n+m,m=n-m,n=n-m;
jc[0]=1;
for (int i=1;i<=m;i++)
jc[i]=jc[i-1]*i%mo,yh[1][i]=i;
for (int i=2;i<=m;i++)
for (int j=i;j<=m;j++)
yh[i][j]=(yh[i][j-1]+yh[i-1][j-1])%mo;
M[0][0]=1;
for (int i=1;i<=K;i++)
{
M[i][0]=1;
for (int j=1;j<=n*m;j++)
M[i][j]=M[i][j-1]*i%mo;
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&K,&mo);
ycl();f[0][0]=1;
for (int i=0;i<K;i++)
for (int j=0;j<=n;j++)
{
if (!f[i][j]) continue;
(f[i+1][j]+=f[i][j])%=mo;
for (int k=1;k<=n-j;k++)
(f[i+1][j+k]+=f[i][j]*yh[k][n-j]%mo*yh[k][m-j]%mo*jc[k]%mo*M[i][(n-j)*k+(m-j)*k-k*k-k]%mo)%=mo;
}
// printf("%lld
",f[K][n]);
for (int i=1,j=1;i<=n;i++,j=-j)
(ans+=f[K][i]*M[K][(n-i)*(m-i)]%mo*j%mo)%=mo;
printf("%lld
",(ans+mo)%mo);
return 0;
}