51Nod 机器人走方格 V3 —— 卡特兰数、Lucas定理

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1120

题解:

1.看到这种题,马上就想到了卡特兰数。但卡特兰数最快也要O(n)的时间复杂度去递推或者预处理,而n的范围是1e9,所以行不通。但发现Mod的值为10007,感觉突破口在里头,但没有头绪。

2.后来发现了Lucas定理:

C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p,p为素数

这个式子大大缩小了n的范围,因此就可以直接上卡特兰数的公式了:

h(n) = C(2n,n) - C(2n,n+1),n=0,1,2...

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <cmath>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <string>
11 #include <set>
12 using namespace std;
13 typedef long long LL;
14 const int INF = 2e9;
15 const LL LNF = 9e18;
16 //const int MOD = 1e9+7;
17 const int MAXN = 1e6+10;
18 
19 const int MOD = 10007;
20 int qpow(int x, int y)
21 {
22     int s = 1;
23     while(y)
24     {
25         if(y&1) s = (s*x)%MOD;
26         x = (x*x)%MOD;
27         y >>= 1;
28     }
29     return s;
30 }
31 
32 int A[2*MOD+10], inv[2*MOD+10];
33 int C(int n, int m)
34 {
35     if(n<m) return 0;
36     return (((A[n]*inv[n-m])%MOD)*inv[m])%MOD;
37 }
38 
39 int lacus(int n, int m)
40 {
41     int s = 1;
42     while(n&&m)
43     {
44         s = (s*C(n%MOD,m%MOD))%MOD;
45         n /= MOD;
46         m /= MOD;
47     }
48     return s;
49 }
50 
51 void init()
52 {
53     A[0] = inv[0] = 1;
54     for(int i = 1; i<=2*MOD; i++)
55     {
56         A[i] = (i*A[i-1])%MOD;
57         inv[i] = qpow(A[i],MOD-2);
58     }
59 }
60 
61 int main()
62 {
63     init();
64     int n;
65     while(scanf("%d",&n)!=EOF)
66     {
67         n--;
68         int ans = (lacus(2*n,n)-lacus(2*n,n+1)+MOD)%MOD;
69         ans = (ans*2)%MOD;
70         printf("%d
", ans);
71     }
72 }
View Code
原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8732689.html