BSOJ4125题解
行列都互不相同,这也太麻烦了!
考虑去掉行或列的限制,然后使用反演。
考虑只有行互不相同的 \(n\times m\) 的矩阵数量为 \(f[n][m]\),显然有:
\[f[n][m]=(c^m)^{\underline n}
\]
发现考虑列的时候,由于行之间一定互不相同,所以不需要去考虑行了。
考虑 \(g[n][m]\) 为所求,要先使用 \(g\) 去演绎 \(f\) 才有可能得到反演的柿子。
此时 \(n\) 已无意义,因为行之间已经互不相同了。于是枚举列的数量表示有这么多个列互不相同。
容易发现相当于是让每一列选择一列 \(g\) 中的,得到演绎柿:
\[f[n][m]=\sum_{i=1}^{m}\begin{Bmatrix}m\\i\end{Bmatrix}g[n][i]
\]
使用斯特林反演有:
\[g[n][m]=\sum_{i=1}^{m}\begin{bmatrix}m\\i\end{bmatrix}(-1)^{m-i}f[n][i]
\]
直接算,\(O(m^2)\)。
#include<cstdio>
const int M=4005,mod=1e9+7;
int n,m,c,S1[M];
signed main(){
int sum(0);scanf("%d%d%d",&n,&m,&c);
S1[0]=1;for(int i=1;i<=m;++i){for(int j=i;j>=1;--j)S1[j]=((i-1ll)*S1[j]+S1[j-1])%mod;S1[0]=0;}
for(int t(c),i=1;i<=m;++i,t=1ll*t*c%mod){
int prod(1);for(int k=0;k<n;++k)prod=1ll*prod*(mod+t-k)%mod;sum=(sum+1ll*(m-i&1?mod-S1[i]:S1[i])*prod)%mod;
}
printf("%d",sum);
}