恰好移动 k 步到达某一位置的方法数目
给你两个 正 整数 startPos 和 endPos 。最初,你站在 无限 数轴上位置 startPos 处。在一步移动中,你可以向左或者向右移动一个位置。
给你一个正整数 k ,返回从 startPos 出发、恰好 移动 k 步并到达 endPos 的 不同 方法数目。由于答案可能会很大,返回对 10^9 + 7 取余 的结果。
如果所执行移动的顺序不完全相同,则认为两种方法不同。
注意:数轴包含负整数。
示例 1:
输入:startPos = 1, endPos = 2, k = 3
输出:3
解释:存在 3 种从 1 到 2 且恰好移动 3 步的方法:
- 1 -> 2 -> 3 -> 2.
- 1 -> 2 -> 1 -> 2.
- 1 -> 0 -> 1 -> 2.
可以证明不存在其他方法,所以返回 3 。
示例 2:
输入:startPos = 2, endPos = 5, k = 10
输出:0
解释:不存在从 2 到 5 且恰好移动 10 步的方法。
提示:
1 <= startPos, endPos, k <= 1000
题解
一看这种规定了移动的步数就知道是用组合数了;如果是动态规划的话肯定不会给出步数。
分析题目
从题目中,我们可以发现:(以下假设m=|endPos-startPos|)
- 当endPos>startPos时,我们有m+(k-m)/2步往右走,(k-m)/2步往左走。
- 当endPos<startPos时,我们有m+(k-m)/2步往左走,(k-m)/2步往右走。
那么方法数就是求C(k,m+(k-m)/2))。
组合数求解新方法
以前我求组合数都是用高中的方法求的:
C
(
m
,
n
)
=
C
m
n
=
m
!
/
(
(
m
−
n
)
!
+
n
!
)
C(m,n)=C_m^n=m!/((m-n)!+n!)
C(m,n)=Cmn=m!/((m−n)!+n!)
而现在大多数人求组合数都是:
C
(
m
,
n
)
=
C
m
n
=
C
m
−
1
n
+
C
m
−
1
n
−
1
C(m,n)=C_m^n=C_{m-1}^n+C_{m-1}^{n-1}
C(m,n)=Cmn=Cm−1n+Cm−1n−1
代码
const int MAX=1005;
const int MOD=1e9+7;
class Solution {
public:
int ret;
// C (n, m) = C (n – 1, m – 1) + C (n – 1, m)
int comb[MAX][MAX];
int numberOfWays(int startPos, int endPos, int k) {
int gap=abs(endPos-startPos);
if(gap>k||(k-gap)%2!=0){
return 0;
}
int m=(k+gap)/2;
comb[0][0]=1;
for(int i=1;i<MAX;i++){
comb[i][0]=comb[i][i]=1;
for(int j=1;j<i;j++){
comb[i][j]=(comb[i-1][j-1]+comb[i-1][j])%MOD;
}
}
return comb[k][m];
}
};