P6076 JSOI2015染色问题
也是BZOJ4497
- 容斥原理: 将条件容斥
首先,去掉“至少只用一种颜色”这个条件: 设 f[i]表示用至多 i 种颜色, 每行每列都染色的格子的方案数
则答案为 \(\sum\limits_{i=0}^{c}(-1)^iC_c^if_{c-i}\) (i为必须忽略的颜色个数)
其次,\(f_i=\sum\limits_{k=0}^{m}(-1)^kC_m^k((i+1)^k-1)^m\) (k为规定必须选的列数)
点击查看代码
#include <stdio.h>
#include <string.h>
typedef long long LL;
const int N = 405, mod = 1e9 + 7;
int f[N], fac[N], inv[N];
int qpow(int b, int p) {
int res = 1;
while(p) {
if(p & 1) res = (LL)res * b % mod;
b = (LL)b * b % mod, p >>= 1;
} return res;
}
inline int C(int n, int m) {
if(n < m) return 0;
return (LL)fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int n, m, c;
int main() {
scanf("%d%d%d", &n, &m, &c);
for(int i = fac[0] = inv[0] = 1; i <= m || i <= c; i ++)
fac[i] = (LL)fac[i - 1] * i % mod, inv[i] = qpow(fac[i], mod - 2);
for(int i = 1; i <= c; i ++) {
for(int k = 0; k <= m; k ++) {
int tmp = qpow((qpow(i + 1, m - k) - 1LL + mod) % mod, n);
if(k & 1) f[i] = (f[i] - (LL)tmp * C(m, k)) % mod;
else f[i] = (f[i] + (LL)tmp * C(m, k) + mod) % mod;
}
}
int res = 0;
for(int i = 0; i <= c; i ++)
if(i & 1) res = (res - (LL)C(c, i) * f[c - i] % mod) % mod;
else res = (res + (LL)C(c, i) * f[c - i] % mod + mod) % mod;
printf("%d\n", res);
return 0;
}