HNOI2009 - 有趣的数列

  • https://www.lydsy.com/JudgeOnline/problem.php?id=1485

  • 把奇数位置的数当成一个左括号和它在序列中的对应位置,偶数位置的当成一个右括号和它的对应位置,会发现答案其实就是卡特兰数列的第 \(n\) 项。

  • 模数不是素数,不能直接计算 \(\dfrac{\binom{2n}{n}}{n+1}\),只能手动约分。。。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long i64;
    
    const int N=2000010;
    
    int n,MOD;
    int pri[N],pd[N],cnt[N];
    
    int mul(int a,int b)
    {
      return i64(a)*b%MOD;
    }
    
    int power(int a,int e)
    {
      int r=1;
      for(;e;e>>=1)
      {
          if(e&1) r=mul(r,a);
          a=mul(a,a);
      }
      return r;
    }
    
    int main()
    {
      cin>>n>>MOD;
      if(n==1)
      {
          printf("%d\n",n%MOD);
          return 0;
      }
      for(int i=2;i<N;++i) pd[i]=i;
      int pc=0;
      for(int i=2;i<N;++i)
      {
          if(pd[i]==i) pri[pc++]=i;
          for(int j=0;i*pri[j]<N;++j)
          {
              pd[i*pri[j]]=pri[j];
              if(i%pri[j]==0) break;
          }
      }
      for(int i=n+2;i<=2*n;++i)
      {
          int v=i;
          while(v>1)
          {
              int d=pd[v];
              int cc=0;
              while(v%d==0)
              {
                  v/=d;
                  ++cc;
              }
              cnt[d]+=cc;
          }
      }
      for(int i=2;i<=n;++i)
      {
          int v=i;
          while(v>1)
          {
              int d=pd[v];
              int cc=0;
              while(v%d==0)
              {
                  v/=d;
                  ++cc;
              }
              cnt[d]-=cc;
              assert(cnt[d]>=0);
          }
      }
      int ans=1;
      for(int i=2;i<N;++i) ans=mul(ans,power(i,cnt[i]));
      printf("%d\n",ans);
      return 0;
    }

猜你喜欢

转载自www.cnblogs.com/arg-53/p/9301958.html
今日推荐