Y – 机器人走方格 V3

  • Post author:
  • Post category:其他


N * N的方格,从左上到右下画一条线。一个机器人从左上走到右下,只能向右或向下走。并要求只能在这条线的上面或下面走,不能穿越这条线,有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10007的结果。

Input

输入一个数N(2 <= N <= 10^9)。

Output

输出走法的数量 Mod 10007。

Sample Input

4

Sample Output

10

卡特兰数+卢卡斯+费马小定理:

分析:列举几个n就会发现,结果就是卡特兰数乘2

卡特兰数:

1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, …

这里用到求卡特兰数的一个公式:h(n)=C(2n,n)-C(2n,n-1)(n=0,1,2,…)

然后其实这就是一个比较裸的卡特兰+卢卡斯模板。

#include <iostream>
#include <cstdio>
#include <string>
#include<cstring>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define N 205
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
int p=1e4+7;
//快速幂
ll quick_pow(ll n,ll m){
    ll ans=1;
    while (m){
        if(m&1)
            ans = ans * n % p;
        n=n*n%p;
        m>>=1;
    }
    return ans;
}
//求组合数C(n,m)
ll C(ll n,ll m){
       if(m>n)return 0;
       ll ans=1;
       for(int i=1;i<=m;i++){
           ll a =(n + i - m) % p;
           ll b = i % p;
           ans = ans * (a * quick_pow(b, p-2) % p) % p;
           //费马小定理求逆元
       }
       return ans;
}
//卢卡斯模板
ll lucas(ll n,ll m){
    if(!m)
        return 1;
    return C(n%p,m%p)*lucas(n/p,m/p)%p;
}
int main()
{
    ll n;cin>>n;
    n-=1;
    ll r=lucas(2*n,n);
    //求卡特兰数:f(n)=C(2n,n)-C(2n,n-1)
    ll es=lucas(2*n,n-1);
    ll res=(r-es+p)%p*2%p;
    cout<<res<<endl;
    return 0;
}



版权声明:本文为weixin_46220615原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。