题目大意:
你现在在位置 $(0,0)$,每一次可以选择以下两种方式的任意一种移动:
- 向下走一格,向右走两格;
- 向下走两格,向下走一格。
求可以到达 $(x,y)$ 的方案总数,对 $10^9+7$ 取模。
解析:
这道题给了一个很好的限制:只能向右、向下走。
观察题目,可以发现如果 $3 mid x+y$,那么方案数是 $0$,因为每一次转移都会使得横纵坐标和加上 $3$。
所以,我们只需列一个方程组,就可以求出向下走 $1$ 格并向右走 $2$ 格的方案次数,与向下走 $2$ 格且向下走 $1$ 格的方案次数。
知道了分别转移的次数,我们就要枚举顺序。
假设第一种方式转移 $a$ 次,第二种方式转移 $b$ 次。
那么,问题就简化成这个样子:
有 $a$ 个 $1$ 与 $b$ 个 $0$ 进行组合,可以制造出多少个不同的数字串 ?
答案显而易见,是 $large{inom {a+b} a}$ 或 $large{inom {a+b} b}$。
当然,要注意本题有取模,求组合数时要预处理逆元。
代码:
#include <cstdio> #define MOD 1000000007 #define INF 1e9 #define eps 1e-6 typedef long long ll; ll x, y, xx, yy, inv[2000010], prod[2000010], ans; int main(){ scanf("%lld%lld", &x, &y); if((x + y) % 3){ puts("0"); return 0; } xx = x - (x + y) / 3; yy = y - (x + y) / 3; if(x < 0 || y < 0) puts("0"); else{ inv[0] = inv[1] = 1; for(ll i = 2; i <= (xx + yy); i++) inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD; for(ll i = 2; i <= (xx + yy); i++) inv[i] = inv[i - 1] * inv[i] % MOD; prod[0] = 1; for(ll i = 1; i <= (xx + yy); i++) prod[i] = prod[i - 1] * i % MOD; ans = prod[xx + yy] * inv[xx] % MOD * inv[yy] % MOD; printf("%lld ", ans); } return 0; }