• bzoj2111ZJ2010排列计数_solution


              -by bzoj 

    http://www.lydsy.com/JudgeOnline/problem.php?id=2111



    考虑第i个位置上的数字的可能性只取决于第i/2位置上的数,以及剩余数集的大小,可以看出一个树形模型

    考虑第i个位置上的数字只会影响第i*2与i*2+1两个位置的可能性,发现这是个二叉树(完全二叉树)

    而且是类似小根堆的形式,于是这个树的形态固定,第1个位置上只能放1;

    这启发我们进一步思考

    对根(第1个位置)来说,他自己是数集中最小的那个,从剩下n-1个数字中,挑一些填满左子树的节点,剩下填右子树,由于只有数字的个数影响结果,所以对左右子树的填法可以看做一个类似的子问题递归进行;

    于是有f[i]=C(sum[i<<1],sum[i<<1]+sum[i<<1|1])*f[i<<1]*f[i<<1|1];

    C为组合数;

    注意组合数的处理细节

    O(nlogn);

    代码:

    #include<cstdio>
    #define LL long long 
    using namespace std;
    int N;
    LL P;
    int sum[2000010];
    LL inv[2000010];
    LL Sqr(LL ,int );
    void dfs(int );
    LL dp(int );
    LL C(int ,int );
    int main()
    {
        int i,j,k;
        scanf("%lld%lld",&N,&P);
        for(i=1;i<=N;i++)
            inv[i]=Sqr(i%P,P-2);
        dfs(1);
        printf("%lld",dp(1));
        return 0;
    }
    LL Sqr(LL x,int n){
        LL ret=1;
        while(n){
            if(n&1)
                (ret*=x)%=P;
            (x*=x)%=P,n>>=1;
        }
        return ret;
    }
    void dfs(int x){
        if((x<<1)<=N)
            dfs(x<<1);
        if((x<<1|1)<=N)
            dfs(x<<1|1);
        sum[x]=sum[x<<1]+sum[x<<1|1]+1;
    }
    LL dp(int x){
        LL a=1,b=1,ret=1;
        if((x<<1)<=N)
            a=dp(x<<1);
        if((x<<1|1)<=N)
            b=dp(x<<1|1);
        ret=a*b%P;(ret*=C(sum[x<<1],sum[x<<1]+sum[x<<1|1]))%=P;
        return ret;
    }
    LL C(int m,int n){
        int i,j=0;
        LL ret=1;
        for(i=1;i<=m;i++)
            if((n-i+1)%P!=0&&i%P!=0)
                (ret*=(((n-i+1ll)*inv[i])%P))%=P;
            else
                j+=((n-i+1)%P==0?1:0)+(i%P==0?-1:0);
        return  j>0?0ll:ret;
    }
  • 相关阅读:
    csu1804
    uvalive4513
    poj3264(Sparse-Table 算法模板)
    uva11107(后缀数组)
    poj2774(最长公共子串)
    uvalive4108(线段树)
    hdu5306 Gorgeous Sequence
    bzoj2823: [AHOI2012]信号塔&&1336: [Balkan2002]Alien最小圆覆盖&&1337: 最小圆覆盖
    bzoj3330: [BeiJing2013]分数
    bzoj1283: 序列
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/8051461.html
Copyright © 2020-2023  润新知