51nod1604 对称的方格颜色

题目描述:

在这里插入图片描述
题目链接

解题思路:

观察题目的性质:
1.中间列不存在第一列和第 m m m列同时不存在的颜色。
证明:假设第 j j j列具有第一列和第 m m m列都没有的颜色。根据题目的性质,我们知道第 [ 1 , j − 1 ] [1,j-1] [1,j1]列的颜色种类和 [ j , m ] [j,m] [j,m]列的颜色种数相同。我们知道 [ 1 , j ] [1,j] [1,j]的颜色种类一定比 [ 1 , j − 1 ] [1,j-1] [1,j1]的多,而 [ j + 1 , m ] [j+1,m] [j+1,m]的颜色种类一定不比 [ j , m ] [j,m] [j,m]的多,由此可知不相等。
2.中间列不存在第一列或者第 m m m列不存在的颜色。
证明同上。
因此我们知道中间列的颜色一定是第一列和第 m m m列颜色的交集。枚举第一列和第 m m m列颜色的交集即可。
这里要额外维护一个 d p dp dp数组, d p [ i ] dp[i] dp[i]表示用i个颜色去染 n n n个方格的方案数,容斥原理维护即可。
复杂度 O ( n 2 ) O(n^2) O(n2)

代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 1e6 + 100;
const int MOD = 1e9 + 7;

int qpow(int x, int n) {
	int res = 1;
	while (n > 0) {
		if (n & 1) res = 1LL * res * x % MOD;
		x = 1LL * x * x % MOD;
		n /= 2;
	}
	return res;
}

int n, m, k;
int fac[N], rev[N], rff[N], dp[N];

int C(int n, int m) {
	if (m < 0 || m > n) return 0;
	return 1LL * fac[n] * rff[m] % MOD * rff[n - m] % MOD;
}

void init() {
	fac[0] = fac[1] = rev[0] = rev[1] = rff[0] = rff[1] = 1;
	for (int i = 2; i < N; i++) {
		fac[i] = 1LL * fac[i - 1] * i % MOD;
		rev[i] = MOD - 1LL * MOD / i * rev[MOD % i] % MOD;
		rff[i] = 1LL * rff[i - 1] * rev[i] % MOD;
	}
	dp[1] = 1;
	for (int i = 2; i <= n; i++) {
		dp[i] = qpow(i, n);
		for (int j = i - 1; j >= 1; j--) {
			dp[i] = (dp[i] - 1LL * C(i, j) * dp[j] % MOD + MOD) % MOD;
		}
	}
}

int main() {
	//freopen("0.txt", "r", stdin);
	scanf("%d%d%d", &n, &m, &k);
	init();
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		int co = qpow(i, n * (m - 2));
		for (int t = 0; i + t <= n && i + 2 * t <= k; t++) {
			ans = (ans + 1LL * C(k, i) * C(k - i, t) % MOD * C(k - i - t, t) % MOD
				* dp[i + t] % MOD * dp[i + t] % MOD
				* co) % MOD;
		}
	}
	if (m == 2) for (int i = 1; 2 * i <= k; i++) ans = (ans + 1LL * C(k, i) * C(k - i, i) % MOD * dp[i] % MOD * dp[i]) % MOD;
	printf("%d\n", ans);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值