AGC002F Leftmost Ball
Link
首先\(k=1\)时答案就是\(1\),因此我们考虑\(k>1\)的情况。
然后我们认为所有颜色都是无序的,最后乘上\(n!\)即可。
设\(f_{i,j}\)表示放了\(i\)种颜色\([1,n]\),\(j\)个颜色\(0\)的方案数,转移分为两种。
第一种是直接在后面放一个颜色\(0\)的球,即\(f_{i,j}\rightarrow f_{i,j+1}\)。
还有一种是在后面放一种颜色的所有球,放完之后总共会有\({(i+1)(k-1)+j}\)个球。
为了防止算重我们需要强制最后一个位置为新放的颜色,剩下的\(k-2\)个球可以放在任意位置,即\({(i+1)(k-1)+j-1\choose k-2}f_{i,j}\rightarrow f_{i+1,j}\)。
#include<cstdio>
const int N=2007,P=1000000007;
int n,m,k,fac[N*N],ifac[N*N],f[N][N];
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
void mul(int&a,int b){a=1ll*a*b%P;}
int C(int n,int m){return 1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
int pow(int a,int b){int r=1;for(;b;b>>=1,mul(a,a))if(b&1)mul(r,a);return r;}
int main()
{
scanf("%d%d",&n,&k),m=n*k,f[0][0]=1;
if(k==1) return puts("1"),0;
fac[0]=1;for(int i=1;i<=m;++i)mul(fac[i]=fac[i-1],i);
ifac[m]=pow(fac[m],P-2);for(int i=m;i;--i)mul(ifac[i-1]=ifac[i],i);
for(int i=0,z=k-1;i<=n;++i,z+=k-1)
for(int j=0;j<=i;++j)
inc(f[i+1][j],1ll*f[i][j]*C(z+j-1,k-2)%P),inc(f[i][j+1],f[i][j]);
mul(f[n][n],fac[n]),printf("%d",f[n][n]);
}