zoukankan      html  css  js  c++  java
  • bzoj1485: [HNOI2009]有趣的数列(Catalan数)

    1485: [HNOI2009]有趣的数列

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 2105  Solved: 1117
    [Submit][Status][Discuss]

    Description

     我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件:

        (1)它是从1到2n共2n个整数的一个排列{ai};

        (2)所有的奇数项满足a1<a3<…<a2n-1,所有的偶数项满足a2<a4<…<a2n

        (3)任意相邻的两项a2i-1与a2i(1≤i≤n)满足奇数项小于偶数项,即:a2i-1<a2i

        现在的任务是:对于给定的n,请求出有多少个不同的长度为2n的有趣的数列。因为最后的答案可能很大,所以只要求输出答案 mod P的值。

     

    Input

    输入文件只包含用空格隔开的两个整数n和P。输入数据保证,50%的数据满足n≤1000,100%的数据满足n≤1000000且P≤1000000000。

     

    Output

    仅含一个整数,表示不同的长度为2n的有趣的数列个数mod P的值。

     

    Sample Input

    3 10

    Sample Output

    5


    对应的5个有趣的数列分别为(1,2,3,4,5,6),(1,2,3,5,4,6),(1,3,2,4,5,6),(1,3,2,5,4,6),(1,4,2,5,3,6)。

    HINT

     

    Source

    /*
    可以把形成序列的过程看成加数的过程,从小到大逐步加(这显然满足限制一),
    然后加数的条件一是从小到大依次放奇数位或偶数位,因此也满足限制二,
    然后无论何时偶数位上的数一定要大于等于奇数位上的数,这样也满足了限制三,
    那么问题就转化成了按照如上条件放数的方案数,联系第二个条件,
    也就是无论何时偶数位上的数一定要大于等于奇数位上的数,可以联想到栈,进栈次数一定要大于等于出栈次数,
    不妨把放在偶数位上看成进栈,放在奇数位上看成出栈,这样就是求一个出栈的序列,也就是Catalan数列。
    由于模数不一定是质数,可以分解质因数求。 
    */
    #include<bits/stdc++.h>
    
    #define ll long long
    #define N 2000007
    
    using namespace std;
    int n,mod,cnt;
    ll pri[N],min_pri[N],num[N],ans=1;
    bool use[N];
    
    void getpri()
    {
        for (int i=2; i<=2*n; i++)
        {
            if (!use[i]) pri[++cnt]=i,min_pri[i]=cnt;
            for (int j=1; pri[j]*i<=2*n&&j<=cnt; j++)
            {
                use[pri[j]*i]=1,min_pri[pri[j]*i]=j;
                if (i%pri[j]==0) break;
            }
        }
    }
    
    ll ksm(ll a,ll b)
    {
        ll res=1;
        while(b){
            if(b&1) res=res*a%mod;
            b>>=1;a=a*a%mod;
        }return res;
    }
    
    void add(int x,int opt)
    {
        while (x!=1)
        {
            num[min_pri[x]]+=opt;
            x/=pri[min_pri[x]];
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&mod);
        getpri();
        for (int i=2*n; i>n; i--) add(i,1);
        for (int i=1; i<=n+1; i++) add(i,-1);
        for (int i=1; i<=cnt; i++) ans=ans*ksm(pri[i],num[i])%mod;
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    CSS盒子模型
    getContextPath、getServletPath、getRequestURI、request.getRealPath的区别
    MYSQL中的CASE WHEN END AS
    单点登录的精华总结
    git&github
    June 21st 2017 Week 25th Wednesday
    June 20th 2017 Week 25th Tuesday
    June 19th 2017 Week 25th Monday
    June 18th 2017 Week 25th Sunday
    June 17th 2017 Week 24th Saturday
  • 原文地址:https://www.cnblogs.com/L-Memory/p/9917084.html
Copyright © 2011-2022 走看看