zoukankan      html  css  js  c++  java
  • BZOJ 1485: [HNOI2009]有趣的数列

    Description

    求长度为 (2n) 的序列.要求

    1. (a_1<a_3<a_5<...<a_{2n-1}) .

    2. (a_2<a_4<a_6<...<a_{2n}) .

    3. (a_{2k-1}<a_{2k} ,1leqslant kleqslant n) .

    Sol

    (Catalan) 数.

    我们发现 (a_{2k}) 必然要大于它前面的所有奇数项.

    如果我们把数字 (1,2,3,...,2n-1,2n) 全部列出来,它只有两种决策,一种是放入奇数项,一种是放入偶数项.

    我们就可以DP了...

    (f[i][j]) 表示前 (i) 个数,其中 (j) 个放入奇数项的方案数.

    转移就是 (f[i][j]=f[i-1][j-1]+f[i-1][j]) .

    不过转移是有条件的,需要满足 (j leqslant  left lfloor frac {i} {2}  ight floor ) .

    然后这就是 (Catalan) 数的一个应用了,不跨过图上直线 (y=x) ,此时只需要令 (k=frac {i} {2},j leqslant k) 就可以看出来了.

    还有一个问题就是 (p) 不是质数,在两个数不互质的时候没有逆元,所以我们需要分解质因数来计算,可以用线性筛筛出最小质因子,每次除去就可以统计出来了.

    因为每个数的质因子个数不超过 (logn) ,所以复杂度 (O(nlogn))

    Code

    /**************************************************************
        Problem: 1485
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:660 ms
        Memory:26680 kb
    ****************************************************************/
     
    #include<cstdio>
    #include<iostream>
    using namespace std;
     
    typedef long long LL;
    const int N = 2000005;
     
    int n,cnt;LL p,ans;
    bool b[N];int minp[N],pr[N],c[N];
     
    void Pre(int LIM){
        minp[1]=1;
        for(int i=2;i<=LIM;i++){
            if(!b[i]) pr[++cnt]=i,minp[i]=cnt;
            for(int j=1;j<=cnt && pr[j]*i<=LIM ;j++){
                b[pr[j]*i]=1,minp[pr[j]*i]=j;
                if(i%pr[j]==0) break;
            }
        }
    }
    LL Pow(LL a,LL b,LL res=1){ for(;b;b>>=1,a=a*a%p) if(b&1) res=res*a%p;return res; }
    void Add(int x,int v){ while(x>1) c[minp[x]]+=v,x/=pr[minp[x]]; }
    int main(){
        cin>>n>>p;
        Pre(2*n);
         
    //  for(int i=1;i<=cnt;i++) cout<<pr[i]<<" ";cout<<endl;
    //  for(int i=1;i<=n;i++) cout<<minp[i]<<" ";cout<<endl;
         
        for(int i=n+2;i<=2*n;i++) Add(i,1);
    //  cout<<"qwq"<<endl;
        for(int i=1;i<=n;i++) Add(i,-1);
         
        ans=1;
        for(int i=1;i<=cnt;i++) ans=ans*Pow(pr[i],c[i])%p;
        return cout<<ans<<endl,0;
    }
    

      

  • 相关阅读:
    C语言与数据库操作入门(Win版)
    用C语言操作MySQL数据库,进行连接、插入、修改、删除等操作
    c语言连接mysql数据库的实现方法
    linux shell 之 crontab(定时任务)详解
    Centos7下面配置静态IP
    安装php
    Deep Learning
    Deep Learning
    Deep Learning
    数据分析
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/5962846.html
Copyright © 2011-2022 走看看