[HNOI2009]有趣的数列

题面:[HNOI2009]有趣的数列

题解:

  ,,,,推了好久也没推出来,,,然而是一个卡特兰数。。。

  因为n比较大,且p不一定为质数,因此可以用一个数组存下每个质因子有几个,对于乘法就累加,除法就减掉,然后把最后剩下的累乘起来就是答案。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define R register int
 4 #define AC 2001000
 5 #define maxn 2000000
 6 #define LL long long
 7 
 8 int tot, n, p;
 9 int pri[AC], last[AC];
10 LL have[AC], ans;
11 bool ispri[AC];
12 
13 void get()
14 {
15     last[1] = 1;
16     for(R i = 2; i <= maxn; i ++)
17     {
18         if(!ispri[i]) pri[++ tot] = i, last[i] = i;
19         for(R j = 1; j <= tot; j ++)
20         {
21             int now = pri[j];
22             if(i * now > maxn) break;
23             ispri[i * now] = true, last[i * now] = now;
24             if(!(i % now)) break;
25         }
26     }
27 }
28 
29 void pre(){
30     scanf("%d%d", &n, &p);
31 }
32 
33 inline void cal(int x){//分解质因数
34     while(last[x] != 1) ++ have[last[x]], x /= last[x];
35 }
36 
37 inline void cut(int x){
38     while(last[x] != 1) -- have[last[x]], x /= last[x];
39 }
40 
41 inline LL qpow(LL x, int have)
42 {
43     LL ans = 1;
44     while(have)
45     {
46         if(have & 1) ans = ans * x % p;
47         x = x * x % p, have >>= 1;
48     }
49     return ans;
50 }
51 
52 void work()
53 {
54     int b = 2 * n;
55     for(R i = 1; i <= b; i ++) cal(i);
56     for(R i = 1; i <= n; i ++) cut(i), cut(i);
57     cut(n + 1), ans = 1;
58     for(R i = 1; i <= b; i ++)
59         if(have[i]) ans = ans * qpow(i, have[i]) % p;
60     printf("%lld\n", ans);
61 }
62 
63 int main()
64 {
65 //    freopen("in.in", "r", stdin);
66     get();
67     pre();
68     work();
69 //    fclose(stdin);
70     return 0;
71 }
View Code

猜你喜欢

转载自www.cnblogs.com/ww3113306/p/9919969.html
今日推荐