P2051
题目描述
题解
1.第
i
i
i行什么都不放。
f
[
i
]
[
j
]
[
k
]
=
f
[
i
]
[
j
]
[
k
]
+
f
[
i
−
1
]
[
j
]
[
k
]
f[i][j][k]=f[i][j][k]+f[i-1][j][k]
f[i][j][k]=f[i][j][k]+f[i−1][j][k]
2.放1个在空的列。空的列是
m
−
j
−
k
m-j-k
m−j−k。
f
[
i
]
[
j
]
[
k
]
=
f
[
i
]
[
j
]
[
k
]
+
f
[
i
−
1
]
[
j
−
1
]
[
k
]
×
(
m
−
(
j
−
1
)
−
k
)
f[i][j][k]=f[i][j][k]+f[i−1][j−1][k]×(m−(j−1)−k)
f[i][j][k]=f[i][j][k]+f[i−1][j−1][k]×(m−(j−1)−k)
3.放1个在有1个的列。
f
[
i
]
[
j
]
[
k
]
=
f
[
i
]
[
j
]
[
k
]
+
f
[
i
−
1
]
[
j
+
1
]
[
k
−
1
]
×
(
j
+
1
)
f[i][j][k]=f[i][j][k]+f[i−1][j+1][k−1]×(j+1)
f[i][j][k]=f[i][j][k]+f[i−1][j+1][k−1]×(j+1)
4.放2个都在空的列。之前状态乘以C(之前空的列,2)。
f
[
i
]
[
j
]
[
k
]
=
f
[
i
]
[
j
]
[
k
]
+
f
[
i
−
1
]
[
j
−
2
]
[
k
]
×
C
(
m
−
(
j
−
2
)
−
k
)
f[i][j][k]=f[i][j][k]+f[i−1][j−2][k]×C(m−(j−2)−k)
f[i][j][k]=f[i][j][k]+f[i−1][j−2][k]×C(m−(j−2)−k)
5.放1个在空的列,1个在有1个的列:
f
[
i
]
[
j
]
[
k
]
=
f
[
i
]
[
j
]
[
k
]
+
f
[
i
−
1
]
[
j
]
[
k
−
1
]
×
j
×
(
m
−
j
−
(
k
−
1
)
)
f[i][j][k]=f[i][j][k]+f[i−1][j][k−1]×j×(m−j−(k−1))
f[i][j][k]=f[i][j][k]+f[i−1][j][k−1]×j×(m−j−(k−1))
6.放2个在有1个的列。
f
[
i
]
[
j
]
[
k
]
=
f
[
i
]
[
j
]
[
k
]
+
f
[
i
−
1
]
[
j
+
2
]
[
k
−
2
]
×
C
(
j
+
2
)
f[i][j][k]=f[i][j][k]+f[i−1][j+2][k−2]×C(j+2)
f[i][j][k]=f[i][j][k]+f[i−1][j+2][k−2]×C(j+2)
初始化: f [ 0 ] [ 0 ] [ 0 ] = 1 f[0][0][0]=1 f[0][0][0]=1
代码
#include<bits/stdc++.h>
#define int long long
#define M 100009
using namespace std;
int read(){
int f=1,re=0;char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-'){f=-1,ch=getchar();}
for(;isdigit(ch);ch=getchar()) re=(re<<3)+(re<<1)+ch-'0';
return re*f;
}
const int mod=9999973;
int C(int x){return (x*(x-1)/2)%mod;}//实际上是C(x,2);
int n,f[109][109][109],ans,m;//f[i][j][k]表示枚举到第i行,前i行中有j行放了一个炮,有k行放了两个炮
signed main(){
n=read(),m=read();
f[0][0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;j+k<=m&&j+k<=2*i;k++){
f[i][j][k]=(f[i][j][k]+f[i-1][j][k])%mod;//什么都不放
if(j>=1) f[i][j][k]=(f[i][j][k]+f[i-1][j-1][k]*(m-(j-1)-k)%mod)%mod;//放1个在空的列
if(k>=1) f[i][j][k]=(f[i][j][k]+f[i-1][j+1][k-1]*(j+1)%mod)%mod;//放1个在有1个的列
if(j>=2) f[i][j][k]=(f[i][j][k]+f[i-1][j-2][k]*C(m-(j-2)-k)%mod)%mod;//放2个都在空的列
if(k>=1) f[i][j][k]=(f[i][j][k]+f[i-1][j][k-1]*j%mod*(m-j-(k-1))%mod)%mod;//放1个在空的列,1个在有1个的列
if(k>=2) f[i][j][k]=(f[i][j][k]+f[i-1][j+2][k-2]*C(j+2)%mod)%mod;//放2个在有1个的列
}
for(int i=0;i<=m;i++)
for(int j=0;i+j<=m&&(i+j)<=2*n;j++)
ans=(ans+f[n][i][j])%mod;
printf("%lld",ans);
return 0;
}