topcoder13444

CountTables

 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 <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll s=0; bool f=0; char ch=' ';
    while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();}
    while(isdigit(ch)) {s=(s<<3)+(s<<1)+(ch^48); ch=getchar();}
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0) {putchar('-'); x=-x;}
    if(x<10) {putchar(x+'0'); return;}
    write(x/10); putchar((x%10)+'0');
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const ll Mod=1000000007;
const int N=4005;
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=1;
    while(y)
    {
        if(y&1) ans=ans*x%Mod; x=x*x%Mod; y>>=1;
    }
    return ans;
}
int main()
{
    int i,j;
    R(n); R(m); R(c);
    fac[0]=1; for(i=1;i<=max(n,m);i++) fac[i]=fac[i-1]*i%Mod;
    invf[m]=Ksm(fac[m],Mod-2); for(i=m-1;i>=0;i--) invf[i]=invf[i+1]*(i+1)%Mod;
    S[0][0]=1;
    for(i=1;i<=m;i++) for(j=1;j<=i;j++) S[i][j]=(S[i-1][j-1]+S[i-1][j]*j%Mod)%Mod;
    ll oo=1,now;
    for(i=1;i<=m;i++)
    {
        oo=oo*c%Mod; now=1;
        for(j=1;j<=n;j++) now=now*(oo-j+1)%Mod;
        for(j=1;j<i;j++) now=(now-S[i][j]*dp[j]%Mod+Mod)%Mod;
        dp[i]=now;
    }
    Wl(dp[m]);
    return 0;
}
/*
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
*/
View Code

 

posted @ 2019-07-21 15:05  yccdu  阅读(155)  评论(0编辑  收藏  举报