bzoj 1485 有趣的数列

传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1485

【题解】

Catalan数,注意不能直接用逆元,需要分解质因数。

 1 # include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int M = 5e5 + 10, N = 2e6 + 10;
 5 
 6 int isp[N];
 7 int p[M], pn;
 8 int n, mod;
 9 int times[M];
10 
11 inline int pwr(int a, int b) {
12     int ret = 1;
13     while(b) {
14         if(b&1) ret = 1ll * ret * a % mod;
15         a = 1ll * a * a % mod;
16         b >>= 1;
17     }
18     return ret;
19 }
20 
21 int main() {
22     cin >> n >> mod;
23     for (int i=2; i<=n+n; ++i) isp[i] = 1;
24     for (int i=2; i<=n+n; ++i) {
25         if(isp[i]) {
26             p[++pn] = i;
27             isp[i] = pn;
28             for (int j=i+i; j<=n+n; j+=i)
29                 isp[j] = 0;
30         }
31     }
32     for (int i=n+1; i<=n+n; ++i) {
33         int t = i;
34         for (int j=1; j<=pn; ++j) {
35             if(t % p[j] == 0) 
36                 while(t % p[j] == 0) ++times[j], t /= p[j];
37             if(t == 1) break;
38             if(isp[t]) {
39                 ++ times[isp[t]];
40                 break;
41             }
42         }
43     }
44 //    for (int i=1; i<=5; ++i) 
45 //        cout << p[i] << ' ' << times[i] << endl;
46     for (int i=2; i<=n+1; ++i) {
47         int t = i;
48         for (int j=1; j<=pn; ++j) {
49             if(t % p[j] == 0) 
50                 while(t % p[j] == 0) --times[j], t /= p[j];
51             if(t == 1) break;
52             if(isp[t]) {
53                 -- times[isp[t]];
54                 break;
55             }
56         }
57     }
58     
59     int ans = 1;
60     for (int i=1; i<=pn; ++i) 
61         if(times[i]) ans = 1ll * ans * pwr(p[i], times[i]) % mod;
62     
63     cout << ans;
64     
65     return 0;
66 }
View Code

猜你喜欢

转载自www.cnblogs.com/galaxies/p/bzoj1485.html
今日推荐