又是一道思维难度很大的题,思路很难想到
首先,不妨假设颜色1~n依次出现,只要最后把答案乘上n!就可以了
并且,如果排列是合法的,那么第i个无色球必然在第i个颜色之前出现
那么,问题就转化为了对于所有n个0和k-1个各种颜色球的排列中,符合上述条件的有多少个。
接着,我们可以发现,符合要求的排列,其实就是图一的一种拓扑序
DP即可,dp[i][j]的意义如图二
两种转移:删去第一行的第一个元素,则直接就是d[i-1][j],另一种则是直接删去第二行的第一个元素及其下的一列
这种情况下,拓扑序就是最左一列的拓扑序与剩下一部分的拓扑序的穿插,预处理组合数即可
就是这样,其他参见代码。
图一:拓扑序的模型
图二:状态dp[i][j]的意义
代码如下:
#include <bits/stdc++.h>
#define LL long long
#define MOD 1000000007
using namespace std;
int N,K;
LL fac[5000010],inv[5000010],ifac[5000010],d[2010][2010];
int main()
{
cin>>N>>K;
if(K==1)
{
cout<<1<<endl;
return 0;
}
fac[0]=inv[0]=ifac[0]=fac[1]=inv[1]=ifac[1]=1;
for(int i=2;i<=5000000;i++)
{
fac[i]=(fac[i-1]*i)%MOD;
inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
ifac[i]=(ifac[i-1]*inv[i])%MOD;
}
d[0][1]=1;
for(int i=2;i<=N;i++)
{
d[0][i]=d[0][i-1]*(fac[i*(K-1)-1]*ifac[K-2]%MOD*ifac[(i-1)*(K-1)]%MOD)%MOD;
}
for(int i=1;i<=N;i++)
{
for(int j=i;j<=N;j++)
{
d[i][j]=(d[i-1][j]+d[i][j-1]*(fac[i+j*(K-1)-1]*ifac[K-2]%MOD*ifac[i+(j-1)*(K-1)]%MOD))%MOD;
// cout<<i<<' '<<j<<' '<<d[i][j]<<endl;
}
}
cout<<(d[N][N]*fac[N])%MOD<<endl;
return 0;
}