topcoder13444
阅读原文时间:2023年07月10日阅读:1

TopCoder - 13444

sol:题意和题解都丢在上面了,自己XJByy了一下

先保证行不同,然后对列容斥,dp[i]表示i列的答案
行不同时i列的答案显然是C(c^i,n)*n!,然后在把列之间相同的去掉,就是把i列分为[1~i-1]组,钦定各组之间互不相同,就是第二类斯特林数,减去S[i][ j=[1,i-1] ]*dp[j]即可

/*
问有多少n*m的矩阵,每个数都在[1,C]内,任两行不完全相同,任两列不完全相同。
*/
#include
using namespace std;
typedef long long ll;
inline ll read()
{
ll s=; bool f=; char ch=' ';
while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();}
while(isdigit(ch)) {s=(s<<)+(s<<)+(ch^); ch=getchar();} return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<) {putchar('-'); x=-x;} if(x<) {putchar(x+''); return;} write(x/); putchar((x%)+''); } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar('\n') const ll Mod=; const int N=; ll n,m,c,dp[N]; //先保证行不同,然后对列容斥,dp[i]表示i列的答案 //行不同时i列的答案显然是C(c^i,n)*n! ll S[N][N],fac[N],invf[N]; inline ll Ksm(ll x,ll y) { ll ans=; while(y) { if(y&) ans=ans*x%Mod; x=x*x%Mod; y>>=;
}
return ans;
}
int main()
{
int i,j;
R(n); R(m); R(c);
fac[]=; for(i=;i<=max(n,m);i++) fac[i]=fac[i-]*i%Mod; invf[m]=Ksm(fac[m],Mod-); for(i=m-;i>=;i--) invf[i]=invf[i+]*(i+)%Mod;
S[][]=;
for(i=;i<=m;i++) for(j=;j<=i;j++) S[i][j]=(S[i-][j-]+S[i-][j]*j%Mod)%Mod;
ll oo=,now;
for(i=;i<=m;i++)
{
oo=oo*c%Mod; now=;
for(j=;j<=n;j++) now=now*(oo-j+)%Mod;
for(j=;j<i;j++) now=(now-S[i][j]*dp[j]%Mod+Mod)%Mod;
dp[i]=now;
}
Wl(dp[m]);
return ;
}
/*
input 2 2 2
output 10

input 1 1 4000
output 4000

input 4000 4000 4000
output 237003303

input 5 5 1
output 0

input 4000 1 4000
output 593395757

input 2 3 5
output 13740
*/