有效涂色问题

原题

# 有效涂色问题

## 题目描述

一共有$n$个格子,$m$种颜色,在每个格子里填涂$m$种颜色中的一种颜色。当$n$个格子都填涂了颜色,且$m$种颜色都被使用过,我们称之为有效填涂,请问有多少种有效填涂的方案。由于方案数可能很大,结果需要对$1e9+7$取模

## 输入格式

一行两个整数,$n、m$。

## 输出格式

一个整数,有效填涂的方案数对$1e9+7$取模的结果

## 样例 #1

### 样例输入 #1

```
5 1
```

### 样例输出 #1

```
1
```

## 样例 #2

### 样例输入 #2

```
5 2
```

### 样例输出 #2

```
30
```

## 提示

1<=m<=n<=5000

分析

二维动态规划,乘法原理

定义dp[i][j]:前i个格子涂j种颜色所获得的方案

分情况讨论

1.填入之前有的一个颜色,获得 之前方案 * j 个方案

2.填入之前没有的一个颜色,获得 之前方案 * (m - j + 1)(剩余的颜色种数) 个方案

两种和获得当前方案

状态转移方程:dp[i][j] = dp[i - 1][j] * j + dp[i - 1][j - 1] * (m - j + 1)

第二种的dp为什么是j - 1?

当前有j种颜色(包括新涂的),之前有j - 1种颜色

dp边界 :dp[1][1]有m种选择

AC代码

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

const int siz = 5005;
const int mod = 1e9 + 7;

int n, m;
int dp[siz][siz];
signed main() {
	cin >> n >> m;
	dp[1][1] = m;
	for (int i = 2; i <= n; i++) {
		for (int j = m; j >= 1; j--) {
			dp[i][j] = dp[i - 1][j] * j % mod + dp[i - 1][j - 1] * (m - j + 1) % mod;
			dp[i][j] %= mod;
		}
	}
	cout << dp[n][m];
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值