【51NOD1120 机器人走方格】卡特兰数+卢卡斯定理

51NOD1120 机器人走方格
题意
就是给你一个nn的方格,从左上到右下画一条线。一个机器人从左上走到右下,只能向右或向下走。并要求只能在这条线的上面或下面走,不能穿越这条线,有多少种不同的走法?
做法
就是把它看成括号匹配问题,向下走看成左括号,向右走看成右括号,就变成了构造一个长度为2
(n-1)的合法括号匹配序列,就是卡特兰数 a n s = C ( 2 n 2 , n 1 ) C ( 2 n 2 , n 2 ) ans = C(2*n-2,n-1)-C(2*n-2,n-2) 最后考虑线上面下面两种走法,答案再乘2即可。这里n很大,考虑用卢卡斯定理解决,但是这里不保证n和Mod互质,但是由于数据水还是过了。

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
#include<set>
#include<vector>
#include <time.h>
#include<string.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <ll, int> pli;
typedef pair <db, db> pdd;

const int maxn = 1e5+5;
const int Mod=10007;
const int INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const double e=exp(1);
const db PI = acos(-1);
const db ERR = 1e-10;

#define Se second
#define Fi first
#define pb push_back
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl

long long Fac[maxn],Inv[maxn],inv[maxn];
void init()
{
    Fac[0]=Inv[0]=Fac[1]=Inv[1]=inv[1]=1;
    for(int i=2;i<maxn;i++)
    {
        Fac[i]=Fac[i-1]*i%Mod;
        inv[i]=inv[Mod%i]*(Mod-Mod/i)%Mod;
        Inv[i]=Inv[i-1]*inv[i]%Mod;
    }
}
long long c(int n,int m)
{
    if(n<m||m<0) return 0;
    return Fac[n]*Inv[m]%Mod*Inv[n-m]%Mod;
}

long long C(int n,int m){
  int ans=1;
  while (n || m)
    ans=ans*c(n%Mod,m%Mod)%Mod,n/=Mod,m/=Mod;
  return ans;
}

int main()
{
    int n;
    scanf("%d",&n);
    init();
    ll ans=(C(2*n-2,n-1)-C(2*n-2,n-2)+Mod)%Mod;
    ans=ans*2%Mod;
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38891827/article/details/84919511