zoukankan      html  css  js  c++  java
  • 1120 机器人走方格 V3(组合数)

    题目实际上是求catalan数的,Catalan[n] = C(2*n,n) / (n+1) = C(2*n,n) % mod * inv[n+1],inv[n+1]为n+1的逆元,根据费马小定理,可以通过快速幂快速求出。

    因为n的数据范围较大,所以要用到卢卡斯定理:若p为素数,那么C(m,n)%p = C(m/p,n/p) * C(m%p,n%p)  % p.从而我们可以递归的可以求出C(m,n),当n==0,返回1.

    因为方格含有两个三角形,所以Catalan[n]*2 即是最终答案

    #include<stdio.h>
    #include<math.h>
    #include<vector>
    #include<stack>
    #include<set>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #define MAXSIZE 10005
    #define INF 0x3f3f3f3f
    using namespace std;
    #define LL long long
    const LL mod = 1e4+7;
    LL inv[mod+10];
    
    LL Pow(LL n,LL m)
    {
        n %= mod;
        LL ans = 1;
        while(m>0)
        {
            if(m%2)
                ans = (ans*n)%mod;
            n = (n*n)%mod;
            m /= 2;
        }
        return ans;
    }
    
    LL C(LL m,LL n) //对mod取模后,m,n的值均小于1e4+7,直接求组合即可
    {
        if(n > m)
            return 0;
        LL ans = 1;
        for(int i=1; i<=n; i++)
        {
            ans = ans*(m-i+1)%mod*inv[i]%mod;
        }
        return ans;
    }
    
    LL Lucas(LL n, LL m) //卢卡斯定理
    {
        if(m==0)
            return 1;
        return Lucas(n/mod,m/mod)%mod*C(n%mod,m%mod)%mod;
    }
    
    LL Solve(LL n)
    {
        LL ans = Lucas(2*n,n)%mod;
        LL Inv = Pow(n+1,mod-2); //inv(n+1)
        ans = ans%mod*Inv%mod;
        return ans * 2 % mod;
    }
    
    int main()
    {
        for(int i=1; i<=mod; i++)
            inv[i] = Pow(i,mod-2); //预处理求出逆元
        LL n;
        scanf("%lld",&n);
        LL ans = Solve(n-1);
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    一些有用的正则
    UNION ALL合表查询
    远程桌面连接:出现身份验证错误,要求的函数不受支持,可能是由于CredSSP加密Oracle修正的解决方法
    Ubuntu20.04安装、配置openvas
    awvs13破解安装、批量扫描脚本
    剑指05题
    时间复杂度o(1), o(n), o(logn), o(nlogn)
    Intellij IDEA 注释模板
    Explain详解
    Hibernate中get()和load()的区别
  • 原文地址:https://www.cnblogs.com/alan-W/p/9034617.html
Copyright © 2011-2022 走看看