• 【BZOJ 1485】[HNOI2009]有趣的数列 卡特兰数


    这个题我是冲着卡特兰数来的所以就没有想到什么dp,当然也没有想到用卡特兰数的原因...........

    你只要求出前几项就会发现是个卡特兰数,为什么呢:我们选择地时候要选择奇数位和偶数位,相邻(一对里面)奇数位小于偶数位而且他们内部分别递增,那么就是在一个1~2*n的数列上选取一些书作为左括号,一些数作为右括号,左括号为奇数位右括号为偶数位,且是合法的匹配因为都是n个,所以我们就是在进行n对括号匹配。

    这道题的分解质因数就用组合数求就好了。就是先筛质数并记录一个数的最小质因子,然后跳着筛,并记录质数个数,最后在对质数进行快速幂(不快速幂也行而且或许更优),效率是O(n*不可忽略的某常数)..

    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef int LL;
    const LL N=2000010;
    LL prime[N],size[N],p,n,len,num[N];
    bool isnot[N];
    void Pre(){
      for(LL i=2;i<=(n<<1);i++){
        if(!isnot[i])prime[++len]=i,num[i]=len;
        for(LL j=1;prime[j]*i<=(n<<1);j++){
          isnot[prime[j]*i]=1,num[prime[j]*i]=j;
          if(i%prime[j]==0)break;
        }
      }
    }
    void get(LL x,LL s){
      while(x!=1){
        size[num[x]]+=s;
        x/=prime[num[x]];
      }
    }
    inline void Pow(long long &ans,LL x,LL y){
      while(y){
        if(y&1)ans=ans*x%p;
        y>>=1,x=x*x%p;
      }
    }
    int main(){
      scanf("%d%d",&n,&p);Pre();
      for(LL i=n+2;i<=(n<<1);i++)get(i,1);
      for(LL i=2;i<=n;i++)get(i,-1);
      register long long ans=1;
      for(LL i=1;i<=len;i++)
        if(size[i])
          Pow(ans,prime[i],size[i]);
      printf("%lld",ans);
    }
  • 相关阅读:
    Codeforces 754A Lesha and array splitting (搜索)
    浅入分析Linux
    MakeFile基本使用
    Mac 安装YCM
    Homebrew 配置
    虚拟机复制操作CentOS6导致eth0转为eth0以至于网络服务启动失败的解决方案
    Kickstart安装
    Linux编译安装MySQL
    Python源码读后小结
    编译原理小结
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7304879.html
Copyright © 2020-2023  润新知