原题
# 有效涂色问题
## 题目描述
一共有$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;
}