#include <iostream>
using namespace std;
int main() {
int n,m;
cin>>n>>m;
int a[1001][1001]={0};
a[1][1]=1;
/*(1e9+7) 是一个 double 类型的表达式,不能用于取模运算 %,因为 % 只能用于整数。
把 1e9 + 7 改为整型常量即可:
*/
const int MOD = 1e9 + 7; // 声明常数
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if((i==1)&&(j==1)) continue;
if (i == 1) {
a[i][j] = a[i][j - 1]; // 第一行只能从左边来
}
else if (j == 1) {
a[i][j] = a[i - 1][j]; // 第一列只能从上边来
}
else {
a[i][j]=(a[i-1][j]+a[i][j-1])%MOD;
}
}
}
cout << a[n][m] << endl;
return 0;
}
🧠 一、什么是动态规划(Dynamic Programming, 简称 DP)?
动态规划是一种将大问题拆解为多个子问题,并利用子问题的解来构建大问题解的算法思想。
它的核心思想是:
避免重复计算 —— 通过 保存子问题的答案(通常用数组),以后遇到相同子问题时直接查表,而不是重新计算。
🔁 二、动态规划的三个要素
- 状态表示(状态定义):用一个数组 dp[i][j] 或 dp[i] 表示某个子问题的解。
- 状态转移方程(递推关系):如何从较小的状态得到当前状态。比如二维斐波那契数列的状态转移:
- 初始状态(边界):最基本的情况怎么处理,通常是 dp[0] 或 dp[1] = ...。

京公网安备 11010502036488号