2017多校第8场 HDU 6143 Killer Names 容斥,组合计数
题目链接: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; }