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,⋯,的排列中, Magic排列的个数模 p的值。

    Sample Input

    20 23

    Sample Output

    16

    HINT

    100%的数据中,1 ≤ N ≤ 106, P ≤ 10^9,p是一个质数。

    题解:题意可转化为:求n个节点能构成的完全二叉堆的个数。显然我们可以求出左右两棵子树的大小,然后分别递归下去即可。

    细节有点多~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    const int maxn=1000010;
    int m=1000000;
    ll n,p;
    ll jc[maxn],jcc[maxn],ine[maxn],f[maxn];
    int Log[maxn];
    ll C(ll a,ll b)
    {
    	if(a<b)	return 0;
    	if(!b)	return 1;
    	if(a<p&&b<p)	return jc[a]*jcc[b]%p*jcc[a-b]%p;
    	return C(a%p,b%p)*C(a/p,b/p)%p;
    }
    ll calc(ll x)
    {
    	if(f[x])	return f[x];
    	ll a=x-(1<<Log[x+1])+1;
    	if(a<(1<<Log[x+1]-1))	a=(1<<Log[x+1]-1)-1+a;
    	else	a=(1<<Log[x+1])-1;
    	return f[x]=C(x-1,a)*calc(a)%p*calc(x-a-1)%p;
    }
    int main()
    {
    	scanf("%lld%lld",&n,&p);
    	if(m>=p)	m=p-1;
    	ll i;
    	jc[0]=jcc[0]=1,ine[0]=ine[1]=1;
    	for(i=2;i<=m;i++)	ine[i]=(p-(p/i)*ine[p%i]%p)%p;
    	for(i=1;i<=m;i++)	jc[i]=jc[i-1]*i%p,jcc[i]=jcc[i-1]*ine[i]%p;
    	for(i=2;i<=n+1;i++)	Log[i]=Log[i>>1]+1;
    	f[0]=f[1]=1;
    	printf("%lld",calc(n));
    	return 0;
    }
  • 相关阅读:
    Java实现OPC通信
    OPCServer:使用KEPServer
    OPCServer:使用Matrikon OPC Server Simulation
    OPC和DCOM配置
    jquery中attr和prop的区别
    jquery 操作checkbox是否选中的正确方法
    GPRS RTU设备OPC Server接口C# 实现
    Raspberry Pi 中安装Mono
    C#中DllImport用法汇总
    HTML <form> 标签的 method 属性
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7367340.html
Copyright © 2011-2022 走看看