【BZOJ】2111: [ZJOI2010]Perm 排列计数 计数DP+排列组合+lucas
2018-05-17 10:30
441 查看
【题目】BZOJ 2111
【题意】求有多少1~n的排列,满足\(A_i>A_{\frac{i}{2}}\),输出对p取模的结果。\(n \leq 10^6,p \leq 10^9\),p是素数。
【算法】计数DP+排列组合+lucas
【题解】令i的父亲为i/2,转化为要求给一棵n个点的完全二叉树编号使得儿子编号>父亲编号。
设\(f[i]\)表示以第i个点为根的子树的编号方案数(1~sz[i]的排列),考虑从两个儿子处转移。
排列的本质是大小关系,所以两个排列组合起来相当于对1~sz[i<<1]和1~sz[i<<1|1]进行任意组合(各自保持顺序),然后从头到尾重编号成1~sz[i<<1]+sz[i<<1|1]。再将新的编号分配回去。
两个固定排列组合的方案数实际上是将sz[i<<1|1]个“1”分成sz[i<<1]+1份的方案数,采用隔板法易得C(sz[i<<1]+sz[i<<1|1],sz[i<<1]),再枚举两个排列,即:
\[f[i]=f[l_i]*f[r_i]*\binom{sz[i]-1}{sz[l_i]}\]
为了方便看,这里\(l_i=i<<1\),\(r_i=i<<1|1\)。
由于模数p可能比n小,会导致没有逆元,所以预处理1~min(n,p-1)的阶乘,然后用lucas求解组合数。
复杂度\(O(n)\)。
注意:n较大时线性预处理阶乘逆元保证复杂度,f数组全部初始化为1。
#include<cstdio> #include<algorithm> using namespace std; const int maxn=2000010;// int n,MOD,fac[maxn],fav[maxn],sz[maxn],f[maxn]; void gcd(int a,int b,int &x,int &y){if(!b){x=1;y=0;}else{gcd(b,a%b,y,x);y-=x*(a/b);}} int inv(int a){int x,y;gcd(a,MOD,x,y);return (x%MOD+MOD)%MOD;} int c(int n,int m){return 1ll*fac *fav[m]%MOD*fav[n-m]%MOD;} int lucas(int n,int m){ if(n<0||m<0||n<m)return 0; if(n<MOD)return c(n,m); return 1ll*c(n%MOD,m%MOD)*lucas(n/MOD,m/MOD)%MOD; } int main(){ scanf("%d%d",&n,&MOD);int mx=min(MOD-1,n); fac[0]=1;for(int i=1;i<=mx;i++)fac[i]=1ll*fac[i-1]*i%MOD; fav[mx]=inv(fac[mx]);for(int i=mx;i>=1;i--)fav[i-1]=1ll*fav[i]*i%MOD;/// for(int i=1;i<=(n<<1|1);i++)f[i]=1; for(int i=n;i>=1;i--){ sz[i]=sz[i<<1]+sz[i<<1|1]+1; f[i]=1ll*f[i<<1]*f[i<<1|1]%MOD*lucas(sz[i]-1,sz[i<<1])%MOD;// } printf("%d",f[1]); return 0; }
相关文章推荐
- [bzoj2111][ZJOI2010]Perm 排列计数 ——问题转换,建立数学模型
- bzoj2111 [ZJOI2010]Perm 排列计数
- BZOJ 2111 ZJOI2010 Perm 排列计数 组合数学+Lucas定理
- 【递推+lucas定理】BZOJ2111 [ZJOI2010]Perm 排列计数
- BZOJ_2111_[ZJOI2010]Perm 排列计数_树形DP+组合数学
- [BZOJ2111][ZJOI2010]Perm 排列计数 && 数学
- 【BZOJ 2111】 [ZJOI2010]Perm 排列计数
- bzoj 2111: [ZJOI2010]Perm 排列计数【树形dp+lucas】
- 【bzoj2111】[ZJOI2010]Perm 排列计数
- BZOJ 2111: [ZJOI2010]Perm 排列计数(简单组合数学)
- 【BZOJ】2111 [ZJOI2010] Perm 排列计数
- 【bzoj2111】【zjoi2010】【perm排列计数】【dp+Lucas定理】
- [BZOJ2111][ZJOI2010]Perm 排列计数(组合数学+lucas定理)
- [BZOJ2111][ZJOI2010]Perm排列计数(组合数学)
- [bzoj2111][ZJOI2010]Perm 排列计数(组合数学)
- BZOJ 2111: [ZJOI2010]Perm 排列计数 DP+lucas定理
- bzoj 2111 [ZJOI2010]Perm 排列计数(DP+lucas定理)
- bzoj 2111: [ZJOI2010]Perm 排列计数 (组合数学+Lucas定理)
- BZOJ 2111: [ZJOI2010]Perm 排列计数|组合数学|Lucas定理|DP
- BZOJ 2111([ZJOI2010]Perm 排列计数-乘法逆元+完全二叉树模型+数列分数表示法)