HDU-5673-Robot(卡特兰数+逆元 / 默慈金数)


Robot

Accepts: 38
Submissions: 146
Time Limit: 12000/6000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
有一个机器人位于坐标原点上。每秒钟机器人都可以向右移到一个单位距离,或者在原地不动。如果机器人的当前位置在原点右侧,它同样可以
向左移动单位距离。一系列的移动(左移,右移,原地不动)定义为一个路径。问有多少种不同的路径,使得nnn秒后机器人仍然位于坐标原点?
答案可能很大,只需输出答案对1,000,000,0071,000,000,0071,000,000,007的模。
输入描述
输入包含多组数据. 第一行有一个整数T(1≤T≤100)T (1\leq T\leq 100)T(1T100), 表示测试数据的组数. 对于每组数据:
输入一个整数 n(1≤n≤1,000,000)n (1\leq n\leq 1,000,000)n(1n1,000,000)
输出描述
对于每组数据,输出一个整数
输入样例
3
1
2
4
输出样例
1
2
9


BC题解:

HDU-5673-Robot(卡特兰数+逆元 / 默慈金数)_第1张图片


数论:带模除法/逆元/费马小定理参考:

https://www.huangwenchao.com.cn/2014/05/mod-div.html



#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <stack>
using namespace std;
const int MAXN = 1e6+7;
const long long MOD = 1e9+7;
long long cat[MAXN];
long long inv[MAXN];
long long A[MAXN],A_inv[MAXN];
long long get_INV(long long a)
{
    if(a<MAXN-1)return inv[a];
    return (long long)get_INV(MOD%a)*(MOD-MOD/a)%MOD;
}
void get_inverse()
{
    inv[1]=1;
    for(int i=2; i<MAXN; ++i)
        inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
}
void get_Catalan()
{
    cat[0]=cat[1]=1;
    for(int i=2; i<MAXN; ++i)
        cat[i]=(((long long)cat[i-1]*(4*i-2)%MOD)*inv[i+1])%MOD;
}
void get_Combination_number()
{
    A[0]=1;
    A_inv[0]=1;
    for(int i=1; i<MAXN; ++i)
    {
        A[i]=(long long)A[i-1]*i%MOD;
        A_inv[i]=get_INV(A[i]);
    }
}
int main()
{
    int T;
    get_inverse();//逆元打表
    get_Catalan();//卡特兰数打表
    get_Combination_number();//组合数打表
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        long long ANS=0;
        for(int i=0; i<=n/2; ++i)
        {
            ANS+=(((A[n]*A_inv[2*i]%MOD)*A_inv[n-2*i])%MOD*cat[i])%MOD;
            ANS%=MOD;
        }
        printf("%I64d\n",ANS);
    }
    return 0;
}


你可能感兴趣的:(C++)