秀秀的照片

题目描述

华华在和秀秀视频时有截很多图。华华发现秀秀的每一张照片都很萌很可爱。为什么会这样呢?华华在仔细看过秀秀的所有照片后,发现秀秀的照片都具有一个相同的性质。
设秀秀的分辨率为m×n,即在水平方向上每一行有m个像素,垂直方向上每一列有n个像素,照片共有m×n个像素。每一个像素都有一个颜色,共有k种颜色。华华宝宝发现无论是沿着哪两列像素的分界线将秀秀的照片分成左右两半(共有m−1种分法),左右两半不同颜色的种数都是相同的。
华华宝宝把自己的发现告诉了秀秀宝宝。现在秀秀想知道当照片分辨率为m×n,像素颜色种数为k(不一定k种颜色都出现)的时候,共有多少张不同的照片满足上面的性质。
由于答案可能很大,你只需输出答案对1e9+7取模的结果即可。

题解

容易通过分析发现中间的那些条的颜色来自于左右两条的并集。于是我们只要枚举总颜色数,和共用颜色数即可,中间组合数很好分析,难点是如何把 k k 个颜色填入 n n 个格子里,这样很难想,因为必须恰好 k k 个。反过来就一目了然:把 n n 个格子放入 k k 个染池,每个池子都要有东西。
这是第二类斯特林数,我们分类最后一个染池有没有东西 f [ i ] [ j ] = f [ i 1 ] [ j 1 ] + f [ i 1 ] [ j ] j f[i][j]=f[i-1][j-1]+f[i-1][j]*j

题解

#include<bits/stdc++.h>
#define maxn 2005
#define MAXN 1000005
#define INF 0x3f3f3f3f
#define LL long long
#define mod 1000000007
#define re register
using namespace std;
LL read(){
    LL res,f=1; char c;
    while(!isdigit(c=getchar())) if(c=='-') f=-1; res=(c^48);
    while(isdigit(c=getchar())) res=(res<<3)+(res<<1)+(c^48);
    return res*f;
}
LL Pow(LL x,int k){
    LL res=1;
    while(k){
        if(k&1) res=res*x%mod;
        x=x*x%mod; k>>=1;
    }
    return res;
}
int n,m,k;
LL ans,s2[maxn][maxn],jc[MAXN],ny[MAXN];
LL C(int a,int b){return jc[a]*ny[b]%mod*ny[a-b]%mod;}
int main(){
    n=read(); m=read(); k=read();
    jc[0]=1; for(re int i=1;i<=k;i++) jc[i]=jc[i-1]*i%mod;
    ny[k]=Pow(jc[k],mod-2); for(re int i=k;i;i--) ny[i-1]=ny[i]*i%mod;
    s2[0][0]=1;
    for(re int i=1;i<=n;i++)
        for(re int j=1;j<=n;j++)
            s2[i][j]=(s2[i-1][j-1]+s2[i-1][j]*j%mod)%mod;
    for(re int i=0;i<=min(n,k);i++){
        LL tmp=C(k,i)*Pow(i,n*(m-2))%mod;
        for(re int j=i;j<=min(n,k);j++){
            (ans+=tmp*C(k-i,j-i)%mod*C(k-j,j-i)%mod*s2[n][j]%mod*jc[j]%mod*s2[n][j]%mod*jc[j]%mod)%=mod;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_32461955/article/details/83548744