AtCoder - ABC 167 - E(数学推理+组合数)

E - Colorful Blocks

题意:

有 m 种颜色,给 n 个方块染色,可以不使用所有颜色,要求最多有 k 对相邻方块同色。问染色的总情况,最终结果模  998244353。

数据范围:

1 ≤ N, M ≤ 2×10^{5}

0 ≤ K ≤ N − 1

思路:

参考博客

观察样例中的112, 121……我们可以将 n 个方块按照颜色分成 t 组,连着的颜色相同的方块归为一组。如:112 中前两个方块是一组;第三个方块是第二组。然后我们可以惊奇地发现将 n 个方块分成t组后,同色的相邻方块的个数为 n - t 。
比如:n = 3,染色为 112 后,分成 2 组,相邻同色的方块有 n - t = 3 - 2 = 1 对。

根据题意要求相邻同色块最多有 k 对,所以 n - t ≤ k,n - k ≤ t ≤ n。枚举 t 的范围确定后,接下来确定如何将 n 个方块划分成 t 组:
我们设 t 个组包含的方块个数依次是 x1,x2,x3……x_{t} 。所以 x1+x2+x3+……+x_{t} = n 。用隔板法,有 n 个方块,在 n - 1 个位置中选择 t - 1 个位置放隔板,将 n 个方块分成 t 组,总共有 C_{n-1}^{t-1} 种选法法。对于每一种选法,先确定第一组的颜色,第一组是m种颜色任选一种都可,共m种选法;之后的第 2~t 组,每一组可选择的颜色是 m 种颜色中除上一组的颜色外的颜色,即每组有 m - 1 种选法,总共 t - 1 组,情况数为 (m-1)^{t-1}

总情况数为C_{n-1}^{t-1}*m*(m-1)^{t-1}

实现:
1. 求 C_{n-1}^{t-1} ,用公式 C_{n}^{m}=\frac{n!}{m!*(n-m)!} 。预处理出 n 范围内的所有阶乘以及阶乘的逆元
2. 用快速幂求(m-1)^{t-1}
3. 注意取模

Code:

#include<bits/stdc++.h>
using namespace std;

#define x first
#define y second
#define int long long
const int dx[] = { 1,-1,0,0 }, dy[] = { 0,0,1,-1 };

const int N = 200010, INF = 0x3f3f3f3f, mod = 998244353;

typedef pair<int, int>PII;

int n, m, k;
int fact[N], infact[N];

int mul(int x, int y)
{
	return x * y % mod;
}

//快速幂
int qmi(int a, int k)
{
	int res = 1;
	while (k)
	{
		if (k & 1)res = res * a % mod;
		a = a * a % mod;
		k >>= 1;
	}
	return res;
}

//根据公式C(n,m)=n!/m!*(n-m)!
int C(int n, int m)
{
	return fact[n] * mul(infact[m], infact[n - m]) % mod;
}

//预处理N范围内的所有阶乘和逆元
void init()
{
	fact[0] = infact[0] = 1;
	for (int i = 1; i <= n; i++)
	{
		fact[i] = fact[i - 1] * i % mod;                          //预处理阶乘
		infact[i] = mul(infact[i - 1], qmi(i, mod - 2));          //预处理阶乘的逆元
	}
}

void solve()
{
	init();
	cin >> n >> m >> k;
	int ans = 0;

	for (int i = n - k; i <= n; i++)
		ans = (ans + mul(mul(m, C(n - 1, i - 1)), qmi(m - 1, i - 1))) % mod;   //m*C(n-1,i-1) * (m-1)^(i-1)

	cout << ans << endl;
}

signed main()
{
	//int t;
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}

	return 0;
}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
吐槽:太菜了,题解摆这都看不懂(╯-_-)╯╧╧。本题注意点:

1. 关键的思路就是对方块根据颜色分组,然后用隔板法确定如何分组,之后对于每一组再确定染色方法。

2. 注意组合数的求法,尤其是阶乘的逆元初始化那块。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值