[ifrog 1049 - Deg-route] 卡特兰数 + Lucas组合数
题目链接:[ifrog 1049 - Deg-route]
题意描述:
从顶点
(0,0)
出发到点
(x,y)
,已知
(x≥y)
,每次可以只可以向上和向右移动,且不能越过对角线,求满足条件的方案数
%104+7
。
解题思路:
下面是若干个关于卡特兰数的链接,以及若干结论:
- 维基百科-卡特兰数
Catalan(n)=Cn2nn+1=(2n)!(n+1)!n!- 卡特兰数的应用之一: Cn 表示所有在 n×n 格点中不越过对角线的单调路径的个数。一个单调路径从格点左下角出发,在格点右上角结束,每一步均为向上或向右。计算这种路径的个数等价于计算Dyck word的个数:X代表“向右”,Y代表“向上”。可以直接用卡特兰数求解。下图为 n=4 的情况:
- 从顶点 (0,0) 出发到点 (x,y) ,每次可以只可以向上和向右移动,且不能 越过 对角线 (x≥y) ,求满足条件的方案数为 Cyx+y−Cy−1x+y 。
- 从顶点 (0,0) 出发到点 (x,y) ,每次可以只可以向上和向右移动,且不能 经过 对角线 (x>y) ,求满足条件的方案数为 Cyx+y−1−Cy−1x+y−1 。
下面对第4条进行解释。
从顶点 (0,0) 出发到点 (x,y) ,每次可以只可以向上和向右移动,且不能 越过 对角线 (x≥y) ,求满足条件的方案数为 Cyx+y−Cy−1x+y 。
从顶点 (0,0) 出发到点 (x,y) :
- 不考虑是否越界的情况,那么所有方案数是 Cyx+y ;
- 考虑越过 y=x 的情况,那么方案数应该是 Cy−1x+y 。即相当于从点 (0,0) 到点 (y−1,y) 的所有方案数。这种情况就已经包含了所有越界的情况了。
- 那么, Cyx+y−Cy−1x+y 就是不越过 y=x 的方案数了。
理解了第4条,第5条就很好理解了。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MOD = 1e4 + 7;
int fac[MOD + 7];
void init() {
fac[0] = 1;
for (int i = 1; i <= MOD; ++i) fac[i] = (LL)fac[i - 1] * i % MOD;
}
LL qpow(LL a, LL b) {
LL x = a % MOD, ret = 1;
while (b) {
if (b & 1) ret = ret * x % MOD;
x = x * x % MOD;
b >>= 1;
}
return ret;
}
LL C(int n, int m, int MOD) {
return m > n ? 0 : fac[n] * qpow((LL)fac[m] * fac[n - m], MOD - 2) % MOD;
}
LL Lucas(LL n, LL m, int MOD) {
return m ? (LL)C(n % MOD, m % MOD, MOD) * Lucas(n / MOD, m / MOD, MOD) % MOD : 1;
}
int T;
LL x, y, ans;
int main() {
init();
cin >> T;
while(T --) {
cin >> x >> y;
ans = Lucas(x + y, y, MOD) - Lucas(x + y, y - 1, MOD);
ans = (ans + MOD) % MOD;
cout << ans << "\n";
}
return 0;
}