【HNOI2009】有趣的数列

题面

https://www.luogu.org/problem/P3200

题解

从小到大给“奇”和“偶”的序列加数。奇的序列的长度不能超过偶的序列的长度,把加入偶序列记做写一个$($,加入奇序列记做写一个$)$,就是一个括号序列问题,所以答案是一个卡特兰数。

要求输出第$n$个卡特兰数的值膜$p$($p$不一定是质数),我们用$H(i)=H(i-1) imes frac{4n-2}{n+1}$来算,把每个数唯一分解(乘除转加减)就行了。(记得这个$trick$还是上梵高课的时候第一次$get$到的)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ri register int
#define N 1000500
using namespace std;

int n,p;
int c[N],f[4*N],prime[N];
int ton[4*N];

void add(int x) {
  while (1) {
    if (!f[x]) break;
    ton[f[x]]++;
    x/=f[x];
  }
  if (x!=1) ton[x]++;
}

void del(int x) {
  while (1) {
    if (!f[x]) break;
    ton[f[x]]--;
    x/=f[x];
  }
  if (x!=1) ton[x]--;
}

int main() {
  cin>>n>>p;
  c[1]=1;
  int cnt=0;
  for (ri i=2;i<=4*N;i++) {
    if (!f[i]) prime[++cnt]=i;
    for (ri j=1;i*prime[j]<=4*N;j++) {
      f[i*prime[j]]=prime[j];
      if (i%prime[j]==0) break;
    }
  }
  for (ri i=2;i<=n;i++) {
    add(4*i-2);
    del(i+1);
  }
  long long ans=1;
  for (ri i=1;i<=4*N;i++) while (ton[i]) ton[i]--,ans*=i,ans%=p;
  cout<<ans<<endl;
  return 0;
}
原文地址:https://www.cnblogs.com/shxnb666/p/11461082.html