zoukankan      html  css  js  c++  java
  • [BZOJ2111] [ZJOI2010]Perm 排列计数

    [BZOJ2111] [ZJOI2010]Perm 排列计数

    Description

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

    Input

    输入文件的第一行包含两个整数 n和p,含义如上所述。

    Output

    输出文件中仅包含一个整数,表示计算1,2,?, n的排列中, Magic排列的个数模 p的值。

    Sample Input

    20 23

    Sample Output

    16

    HINT

    (1leq nleq 10^6)

    试题分析

    不难发现这是一棵大根堆,直接dp就好了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<algorithm>
    using namespace std;
      
    #define LL long long
      
    inline LL read(){
        LL x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const LL MAXN=1100001;
    const LL INF=999999;
      
    LL N,P; LL fac[MAXN+1];
    LL c[MAXN+1];
      
    inline LL Pow(LL a,LL b){
        LL ans=1LL;
        while(b){
            if(b&1) ans=ans*a%P;
            a=a*a%P; b>>=1;
        } return ans;
    }
    inline LL Lucas(LL N,LL M){
        if (M>N) return 0; if(M==N) return 1;
        if (N<P&&M<P) return (fac[N]*Pow(fac[N-M],P-2)%P*Pow(fac[M],P-2)%P)%P;
        else return Lucas(N/P,M/P)*Lucas(N%P,M%P)%P;
    }
    inline LL dp(LL k){
        if(k==1) return 1; if(!k) return 1; --k;
        LL l=1,r=19,cnt=0; while(l<=r){
            LL mid=(l+r)>>1;
            if(c[mid]<=k&&k-c[mid]>=c[mid-1]) cnt=mid,l=mid+1;
            else r=mid-1;
        }LL tmp=cnt-1; if(2*c[cnt]<=k) tmp++; LL L,R;
        if(tmp==cnt-1) R=k-c[cnt],L=c[cnt]; else L=c[cnt]+k-2*c[cnt],R=k-L;
        return Lucas(k,L)*dp(L)%P*dp(R)%P;
    }
      
    int main(){
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        N=read(),P=read(); fac[1]=1;
        for(LL i=2;i<=N;i++) fac[i]=fac[i-1]*i%P;
        for(LL i=1;i<=19;i++) c[i]=c[i-1]+(1LL<<(i-1));
        printf("%lld
    ",dp(N));
        return 0;
    }
    
    
  • 相关阅读:
    android bluetooth 蓝牙4.0 +HC-08模块
    android 调用默认浏览器 打开指定网页
    checkSelfPermission 找不到 Android 动态权限问题
    C# 使用 USB转串 接收数据 问题
    Mysql 保留最新的10条数据
    Android Fragment 开发(一)
    python IP地址转16进制
    Android Socket 遇到的Soure Not Find 错误
    Linux 修改时区 不用重启
    XML Publisher 并发程序由于 输出提交处理程序提交失败
  • 原文地址:https://www.cnblogs.com/wxjor/p/9540498.html
Copyright © 2011-2022 走看看