• [HNOI2009]有趣的数列


    [HNOI2009]有趣的数列

    有一个长度为2n的1~2n的全排列,保证其奇数项递增,偶数项递增,并且相邻的奇数项和偶数项,后面的偶数项大于奇数项的方案数(mod p,n<=1000000,P<=1000000000)

    注意到2n,实际上也就猜到它可能为catalan数列了,再看看样例,(1,2,5,14),显然为catalan数,故可以猜测为catalan数,在套个质因数分解阶乘求组合数上去就可以了。

    现在在于如何证明,注意到元素不为2个,于是考虑已学模型有多个元素的自然也只有栈,于是考虑去构造栈的模型,因为有递增的要求,所以入栈序必然要让其为递增的,即有1~2n等着去入栈,显然每次入栈的数要比前面都要大,然而又要想办法把它压到n个元素,栈只有n个元素,于是自然会给出两个容器,一个装奇数,一个装偶数,自然奇数容器里面会是递增的,而偶数容器也一样,但是问题在于偶数容器里面是否能保证每个偶数都要对应比奇数大,显然按照我们这种入栈的方式,只要保证任意一次操作偶数入栈的数量比奇数入栈次数少即可,于是也就成功地转化成了catalan模型。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define ll long long
    using namespace std;
    bool check[2000001];
    int yyb,prime[200000],pt;
    il void sieve(int);
    il int cat(int),pow(int,int);
    int main(){
        int n;
        scanf("%d%d",&n,&yyb),sieve(n<<1);
        printf("%d",cat(n));
        return 0;
    }
    il void sieve(int n){
        int i,j;
        for(i=2;i<=n;++i){
            if(!check[i])prime[++pt]=i;
            for(j=1;j<=pt&&prime[j]<=n/i;++j){
                check[i*prime[j]]|=true;
                if(!(i%prime[j]))break;
            }
        }
    }
    il int pow(int x,int y){
        int ans(1);while(y){
            if(y&1)ans=(ll)ans*x%yyb;
            x=(ll)x*x%yyb,y>>=1;
        }return ans;
    }
    il int cat(int n){
        int n2(n<<1),i,j,tr(0),xdk(n+1),
            ans(1);
        for(i=1;i<=pt;++i,tr&=0){
            for(j=n2;j;j/=prime[i])tr+=j/prime[i];
            for(j=n;j;j/=prime[i])tr-=j/prime[i]<<1;
            while(!(xdk%prime[i]))xdk/=prime[i],--tr;
            ans=(ll)ans*pow(prime[i],tr)%yyb;
        }return ans;
    }
    
    
  • 相关阅读:
    vue-cli+typescript 搭建
    es6基础知识
    上机作业六 磁盘管理综合测试2019 7 31
    上机作业五 磁盘配额 2019 7 2
    上机作业四 磁盘管理 2019 7 31
    上机作业三 账号管理2019 7 31
    上机作业 2 2019/7/26
    Linux系统管理06--磁盘管理
    Linux系统管理05--权限及归属管理
    chapter06-07磁盘管理
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10804247.html
Copyright © 2020-2023  润新知