zoukankan      html  css  js  c++  java
  • BZOJ2111:[ZJOI2010]排列计数——题解

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

    https://www.luogu.org/problemnew/show/P2606#sub

    称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值

    画成二叉树后容易发现这就是一个小根堆。

    于是就变成了求符合条件的小根堆数量。

    显然根只能放当前最小数,然后给左子树分配左子树大小个数,右子树同理。

    所以就有f[i]=C(i-1,l)*f[l]*f[r]。

    另外这题卡快速幂的log,所以预处理。

    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1e6+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    int lg[N],f[N],inv[N],fac[N];
    int qpow(ll k,int n,int p){
        int ans=1;
        while(n){
        if(n&1)ans=(ll)ans*k%p;
        k=(ll)k*k%p;n>>=1;
        }
        return ans;
    }
    int C(int n,int m,int p){
        if(m>n)return 0;
        if(m==n)return 1;
        return (ll)fac[n]*inv[m]%p*inv[n-m]%p;
    }
    int lucas(int n,int m,int p){
        int ans=1;
        while(n&&m&&ans){
        ans=(ll)ans*C(n%p,m%p,p)%p;
        n/=p,m/=p;
        }
        return ans;
    }
    inline int lsize(int n){
        int c=lg[n]+1;
        if(c==1)return 0;
        int t=n-(1<<c-1)+1;
        return (1<<c-2)-1+min((1<<c-1>>1),t);
    }    
    int main(){
        int n=read(),p=read();
        
        lg[1]=0;fac[1]=1;
        for(int i=2;i<=n;i++){
        lg[i]=lg[i-1];
        if((1<<lg[i]+1)==i)lg[i]++;
        fac[i]=(ll)fac[i-1]*i%p;
        }
        
        int mx=min(p-1,n);
        inv[mx]=qpow(fac[mx],p-2,p);
        for(int i=mx-1;i>=0;i--)inv[i]=(ll)inv[i+1]*(i+1)%p;
        
        f[1]=f[2]=1;
        for(int i=3;i<=n;i++){
        int l=lsize(i);
        f[i]=(ll)lucas(i-1,l,p)*f[l]%p*f[i-l-1]%p;
        }
        printf("%d
    ",f[n]);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    笨办法41学会说面向对象【我有新书啦!!!
    pip安装及使用
    Office相关
    python各种学习链接
    3000问
    python2代码批量转python3
    啊——回来了_(:з」∠)_
    停更!
    win10 adb(Android Debug Bridge)导出日志
    docker镜像管理基础操作
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8970665.html
Copyright © 2011-2022 走看看