题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6143
题意:m种颜色需要为两段长度为n的格子染色,且这两段之间不能出现相同的颜色,问总共有多少种情况。
解法:枚举要为这两段分配的颜色数目分别为 i,j ,则在第一段总共有 C(m,i) 种选取方案,在第二段总共有 C(m−i,j) 种选取方案。而在每段内部,我们设 F(n,x) 为长度为 n 的格子使用 x 种颜色(等于 x )染色的方案数。则根据容斥原理 F(n,x)=x^n−C(x,1)*(x−1)^n+C(x,2)*(x−2)^n−C(x,3)*(x−3)^n+...于是最终的结果便是所有 C(m,i)F(n,i)×C(m−i,j)F(n,j) 之和。
补充:这个题还可以利用斯特林数来做
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9+7;
LL n,m,C[2005][2005],cal[2005];
LL qsm(LL a, LL n){
LL ret = 1;
while(n){
if(n&1) ret=ret*a%mod;
a=a*a%mod;
n>>=1;
}
return ret;
}
void pre_deal()
{
C[0][0]=1;
for(int i=1; i<=2001; i++){
C[i][0]=1;
for(int j=1; j<=i; j++){
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
}
}
int main()
{
pre_deal();
int T;
scanf("%d", &T);
while(T--)
{
scanf("%lld%lld", &n,&m);
LL ans=0;
for(LL i=1; i<=n; i++){
cal[i]=qsm(i,n);
for(LL j=1;j<i;j++){
cal[i]-=C[i][j]*cal[j]%mod;
cal[i]=(cal[i]+mod)%mod;
}
}
for(LL i=1; i<=n; i++){
if(i>=m) break;
for(LL j=1; j<=n; j++){
if(j>m-i) break;
ans += C[m][i]*cal[i]%mod*C[m-i][j]%mod*cal[j]%mod;
ans %= mod;
}
}
printf("%lld\n", ans);
}
return 0;
}