• 【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);
    }
  • 相关阅读:
    160628、利用Oracle rownum让表排序字段值连续
    160627、你想知道的关于JavaScript作用域的一切
    160624、Spark读取数据库(Mysql)的四种方式讲解
    160623、理解 Promise 的工作原理
    160622、详解JavaScript变量提升
    160621、Java注解教程及自定义注解
    详解JavaScript数组过滤相同元素的5种方法
    box-shadow
    Axios 中文说明
    一步一步学Vue(九) 路由元数据
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7304879.html
Copyright © 2020-2023  润新知