HNU 12933 Random Walks Catalan数 阶乘求逆元新技能

  一个Catalan数的题,打表对每个数都求一次逆元会T,于是问到了一种求阶乘逆元的打表新方法。 比如打一个1~n的阶乘的逆元的表,假如叫inv[n],可以先用费马小定理什么的求出inv[n],再用递推公式求出前面的项。

  我们记数字 x 的逆元为f(x) (%MOD)。

  因为 n! = (n-1)! * n

  所以 f(n!) = f( (n-1)! * n) = f( (n-1)! ) * f(n)。

  所以 f( (n-1)! ) = f(n!) * f( f(n) ) = f(n!) * n   (逆元的逆元就是他自身)

这样子我们就可以用后项推出前面的项了。

题目是说,有一个人从0点开始走路,每次可以向前走或者向后走,每次可以走一步,但是所有的位置必须大于等于0,问走过2n步之后又回到0点有多少种方法。

  其实,如果我们把向前走看做是进栈,向后走看做是出栈,方法数就是Catalan数。

  所以我们只需要打一张表然后查表就好了。

代码: 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <string>
 8 #include <queue>
 9 #include <stack>
10 #include <vector>
11 #include <map>
12 #include <set>
13 #include <functional>
14 #include <cctype>
15 #include <time.h>
16
17 using namespace std;
18
19 typedef __int64 ll;
20
21 const int INF = 1<<30;
22 const int MAXN = (int) 2e6+55;
23 const ll MOD = (ll) 1e9+7;
24
25 ll ans[MAXN];
26 ll fac[MAXN];
27 ll inv[MAXN];
28
29 inline ll myPow(ll x, ll n) {
30     ll res = 1;
31     while (n>0) {
32         if (n&1) res = (res*x)%MOD;
33         x = (x*x)%MOD;
34         n >>= 1;
35     }
36     return res;
37 }
38
39 int main() {
40     #ifdef Phantom01
41         freopen("HNU12933.txt", "r", stdin);
42     #endif //Phantom01
43
44     fac[0] = 1;
45     for (int i = 1; i < MAXN; i++) fac[i] = (fac[i-1]*i)%MOD;
46     inv[MAXN-1] = myPow(fac[MAXN-1], MOD-2);
47     for (int i = MAXN-2; i > 0; i--) {
48         inv[i] = (inv[i+1]*(i+1))%MOD;
49     }
50
51     for (int i = 1; i < (MAXN>>1); i++)
52         ans[i] = (((fac[2*i]*inv[i+1])%MOD)*inv[i])%MOD;
53
54     int T;
55     scanf("%d", &T);
56
57     int n;
58     while (T--) {
59         scanf("%d", &n);
60         printf("%I64d\n", ans[n]);
61     }
62
63     return 0;
64 }

其中,这个是用来打阶乘逆元的:

1     //阶乘
2     fac[0] = 1;
3     for (int i = 1; i < MAXN; i++) fac[i] = (fac[i-1]*i)%MOD;
4     //逆元
5     inv[MAXN-1] = myPow(fac[MAXN-1], MOD-2);
6     for (int i = MAXN-2; i > 0; i--) {
7         inv[i] = (inv[i+1]*(i+1))%MOD;
8     }

时间: 2024-10-11 16:18:51

HNU 12933 Random Walks Catalan数 阶乘求逆元新技能的相关文章

HDU3240-Counting Binary Trees(Catalan数+求逆元(非互质))

Counting Binary Trees Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 564    Accepted Submission(s): 184 Problem Description There are 5 distinct binary trees of 3 nodes: Let T(n) be the number

Catalan数

[问题描述]对于一个栈,已知元素的进栈序列,判断一个由栈中所有元素组成的排列的出栈序列. 有N个数,则代表入栈序列为1,2,3,4,5...,N.求所有可能的出栈序列和总数. 代码如下 #include<iostream> #include<vector> #include<algorithm> #include<string> #include<stdio.h> using namespace std; int N = -1; int sum

【64测试20161112】【Catalan数】【数论】【扩展欧几里得】【逆】

Problem: n个人(偶数)排队,排两行,每一行的身高依次递增,且第二行的人的身高大于对应的第一行的人,问有多少种方案.mod 1e9+9 Solution: 这道题由1,2,5,14 应该想到Catalan数,但是我却花了两个小时去找递推式. 首先 Catalan数 : 基本规律:1,2,5,14,42,132,.......... 典型例题: 1.多边形分割.一个多边形分为若干个三角形有多少种分法. C(n)=∑(i=2...n-1)C(i)*C(n-i+1) 2.排队问题:转化为n个人

关于Catalan数

问题的由来:编号为 1 到 n 的 n 个元素,顺序的进入一个栈,则可能的出栈序列有多少种? 对问题的转化与思考:n 个元素进栈和出栈,总共要经历 n 次进栈和 n 次出栈.这就相当于对这 2n 步操作进行排列.问题等价于:n个1和n个0组成一2n位的2进制数,要求从左到右扫描,1的累计数不小于0的累计数,试求满足这条件的数有多少? 解答: 设P2n为这样所得的数的个数. 在2n位上填入n个1的方案数为 C(n 2n)不填1的其余n位自动填以数0.从C(n 2n)中减去不符合要求的方案数即为所求

POJ 2084 Catalan数

[题意]: 一个环上有2*N个连续的数,求将这些数两两连接且连接的边不相交的方法数. [知识点]: 数学+Catalan数 令h(1)=1,h(0)=1 递归式1:h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (其中n>=2) 递归式2:h(n)=((4*n-2)/(n+1))*h(n-1); 该递推关系的解为:h(n)=C(2n,n)/(n+1) (n=1,2,3,...) [题解]: Catalan数典型的应用,2*N的答案为h(N). [

一天一道算法题---6.11---大数阶乘

感谢微信平台----一天一道算法题----每天多一点进步 大数的概念 感觉是我接触acm 1 2 个月之后才有的....64位的Long long 和 __int64 也大概都是那时候才有的.. 大数 相加 相乘 相除 求余  相减不知道 有没有... 都是应该要掌握的.. 可能 我也会陆续把上面的全慢慢贴上来 // 呆会就直接把 微信提供的代码给贴上来了  先要去次午饭了 早饭 午饭永远是连一起的 .......... // 刚刚碰到个最小生成树的题 第一次用了邻接表去做 蛮cool == 一

(转载)Catalan数——卡特兰数

Catalan数--卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.Catalan数的定义令h(1)=1,Catalan数满足递归式:h(n) = h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1),n>=2该递推关系的解为:h(n) = C(2n-2,n-1)/n,n=1,2,3,...(其中C(2n-2,n-1)表示2n-2个中取n-1个的组合数) 问题描

Catalan数的部分应用

卡特兰数用于解决一些特定的排列问题,一般是求解有多少种排列.. Catalan数的定义: (1)当n=1时,C(1)=1. (2)当n>1时,C(n) = C(1)*C(n-1) + C(2)*C(n-2) + ... + C(n-1)*C(1) (3)当然,也可以这样算: (4)当然,还能这样算: (5)更厉害的,是可以这样算,只是不大准而已: (ps:这些都是经过证明的公式) 注:所有的奇卡塔兰数(即n为奇数)Cn都满足. 一般来说,求卡特兰数有个基本问题,而其他问题一般可以转成这个问题.这

codevs 1086 栈(Catalan数)

题目描述 Description 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). 栈的重要性不言自明,任何一门数据结构的课程都会介绍栈.宁宁同学在复习栈的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙 宁宁考虑的是这样一个问题:一个操作数序列,从1,2,一直到n(图示为1到3的情况),栈A的深度大于n. 现在可以进行两种操作, 1.将一个数,从操