LOJ 10239 有趣的数列

LOJ 10239 有趣的数列

首先可以将奇数视作入栈,偶数视作出栈,那么它是卡特兰数,其实打表也能看出来,而且好像可以用dp?

不过这道题的难点不在这里,p不是素数,所以不能用求逆元来做,不过前50%的分可以用杨辉三角+达标拿到,之后的分就要用到质因数分解了。

求卡特兰数的公式:$h[n]=\frac{C_{2n}^n}{n+1}$,化简之后将其分解,一开始我并没有按质因数分解,结果T了,分解质因数要更快一点。

 1 void add(int x,int nu)
 2 {
 3     for(int i=1;prime[i]*prime[i]<=x;i++)
 4     while(x%prime[i]==0)
 5     {
 6         cnt[prime[i]]+=nu;
 7         x/=prime[i];
 8     }
 9     cnt[x]+=nu;
10 }
11 for(int i=n+2;i<=2*n;i++)add(i,1);
12     for(int i=2;i<=n;i++)add(i,-1);
13     LL ans=1;
14     for(int i=2;i<=2*n;i++)
15         for(int j=1;j<=cnt[i];j++)
16             ans=ans*i%p;
代码实现
 1 #include<iostream>
 2 #include<cstdio>
 3 #define LL long long
 4 //#define int LL
 5 using namespace std;
 6 int n,p;
 7 int cnt[2000010];
 8 int prime[20010],num;
 9 bool isprime[20010];
10 #define N 20000
11 void s()
12 {
13     for(int i=2;i<=N;i++)isprime[i]=1;
14     for(int i=2;i<=N;i++)
15     {
16         if(isprime[i])prime[++num]=i;
17         for(int j=1;j<=num&&i*prime[j]<=N;j++)
18         {
19             isprime[i*prime[j]]=0;
20             if(!i%prime[j])break;
21         }
22     }
23 }
24 void add(int x,int nu)
25 {
26     for(int i=1;prime[i]*prime[i]<=x;i++)
27     while(x%prime[i]==0)
28     {
29         cnt[prime[i]]+=nu;
30         x/=prime[i];
31     }
32     cnt[x]+=nu;
33 }
34 signed main()
35 {
36     s();
37     cin>>n>>p;
38     for(int i=n+2;i<=2*n;i++)add(i,1);
39     for(int i=2;i<=n;i++)add(i,-1);
40     LL ans=1;
41     for(int i=2;i<=2*n;i++)
42         for(int j=1;j<=cnt[i];j++)
43             ans=ans*i%p;
44     cout<<ans<<endl;
45 }
完整代码

 

posted @ 2019-07-22 06:20  Al_Ca  阅读(160)  评论(0编辑  收藏  举报
ヾ(≧O≦)〃嗷~