您的位置:首页 > 其它

hdu 5673 robot【默慈金数or卡特兰数】

2016-04-26 20:33 288 查看
补充知识:

卡特兰数

Catalan(n)=Cn2nn+1

Catalan(n)=4n−2n+1∗Catalan(n−1)

默慈金数

Mn=∑n/2i=0C2in∗Catalan(i)

Mn+1=Mn+∑n−1i=0MiMn−1−i=(2n+3)Mn+3nMn−1n+3

线性求解1~p-1mod p的逆元

inv[i] = (p - p / i) * inv[p%i] % p。

详情参考:

默慈金数 http://blog.csdn.net/acdreamers/article/details/41213667

线性求逆元 http://blog.miskcoo.com/2014/09/linear-find-all-invert

题目大意:

机器人只能在原点及原点右侧,符合规定下可以选择左移一个、右移一个或原地不动,起点在原点,问有几种方式使机器人n次操作后回到原点,结果对1e9+7取余。

思路:

机器人最多走到n/2处;

在0-n/2中的i处,走到i在回到原点的方式有C2in∗Catalan(i)种;

因此ans(n)=∑n/2i=0C2in∗Catalan(i)。

也可以直接套默慈金数递推公式。

1.默慈金数代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;
const LL mod = 1e9 + 7;
const LL MAXN = 1e6 + 100;
LL inv[MAXN], m[MAXN];

int main(int argc, char const *argv[])
{
inv[1] = 1;
for(int i = 2; i < MAXN; i++)
inv[i] = (mod - mod / i) * inv[mod % i] % mod; //预处理逆元
m[1] = 1;
m[2] = 2;
for(int i = 3; i < MAXN; i++)  //默慈金数打表
{
m[i] = (2 * i + 1) * m[i-1] % mod + 3 * (i - 1) * m[i-2] % mod;
m[i] = m[i] % mod * inv[i+2] % mod;
}

int t;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
printf("%I64d\n", m
);
}
return 0;
}


2.catalan数

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;
const LL mod = 1e9 + 7;
const LL MAXN = 1e6 + 100;
LL inv[MAXN], c[MAXN], cat[MAXN];

int main(int argc, char const *argv[])
{
inv[1] = 1;
for(int i = 2; i < MAXN; i++)
inv[i] = (mod - mod / i) * inv[mod % i] % mod;
cat[0] = 1;
cat[1] = 1;
for(int i = 2; i < MAXN; i++) //预处理卡特兰数
{
cat[i] = (4 * i - 2) * cat[i-1] % mod;
cat[i] = cat[i] * inv[i+1] % mod;
}

int t;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
c[0] = 1;
for(int i = 1; i <= n; i++)  //c(n i)组合数
{
c[i] = (n - i + 1) * c[i-1] % mod;
c[i] = c[i] * inv[i] % mod;
}

LL ans = 0;
for(int i = 0; i <= n/2; i++)
{
ans += c[i<<1] * cat[i] % mod;
ans %= mod;
}
printf("%I64d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息