首页 > 技术文章 > HNU 12933 Random Walks Catalan数 阶乘求逆元新技能

Phantom01 2014-08-27 16:31 原文

  一个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 }
View Code

 

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

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     }
View Code

 

推荐阅读