51nod 1120 机器人走方格 V3 lucas+卡特兰+逆原 好题

来源:互联网 发布:cocos2d js protobuf 编辑:程序博客网 时间:2024/04/30 09:59

 首先通过找规律我们发现就是卡特兰数的2倍。所以我们从这里开始入手做。

第一步:卡特兰数的表达式为C(2n, n) / (n + 1)

第二步:简化,因为他要求%p,而p又是一个素数。所以我们运用lucas定理。

lucas定理用于解决C(n,m)%p的问题。C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p

第三步:对于简化完的求组合数,我们用逆原来解决组合数的中的除法问题。

第四步:最后C(2n,n)求出来了,要让他除以n+1,还是要利用逆原解决除法问题。




#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int mod=10007;
long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int r=exgcd(b,a%b,x,y);
    int t=x; x=y; y=t-(a/b)*y;
    return r;
}
long long zuhe(long long x,long long y)
{
    long long  i,x1=1,y1=1,x2=0,y2=0,j=2;
    for(i=x;i>y;i--)  //分子
        x1=x1*i%mod;


    for(i=j;i<=y;i++) //分母
        y1=y1*i%mod;


    exgcd(y1,mod,x2,y2); //对分母求逆原
    while(x2<0) x2+=mod;
    return x1*x2%mod;//化除为乘
}
long long lucas(long long n,long long m)
{
    return m==0?1:zuhe(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}
int main()
{
    int n;
    while(cin>>n)
    {
        n--;
        long long d1,d2;
        long long x=lucas(2*n,n);
        long long d=exgcd(n+1,mod,d1,d2);//求逆原
        while(d1<0) d1+=mod;
        cout<<2*x*d1%mod<<endl;//化除为乘
    }
    return 0;
}

原创粉丝点击