[JSOI2015]染色问题

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;
}
posted @ 2022-10-13 19:02  azzc  阅读(59)  评论(0编辑  收藏  举报