首页 > 代码库 > BZOJ2111: [ZJOI2010]Perm 排列计数

BZOJ2111: [ZJOI2010]Perm 排列计数

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

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

题解:注意到形成一个树状结构,如果不妨设f[i]为i所在子树分配s[i]个节点的方案数。

          那么有递推式:f[i]=f[i<<1]*f[i<<1|1]*c(s[i]-1,s[i<<1])

          然后就lucas定理算算组合数就可以了。

代码:

技术分享
 1 #include<cstdio> 2  3 #include<cstdlib> 4  5 #include<cmath> 6  7 #include<cstring> 8  9 #include<algorithm>10 11 #include<iostream>12 13 #include<vector>14 15 #include<map>16 17 #include<set>18 19 #include<queue>20 21 #include<string>22 23 #define inf 100000000024 25 #define maxn 2000000+526 27 #define maxm 200000+528 29 #define eps 1e-1030 31 #define ll long long32 33 #define pa pair<int,int>34 35 #define for0(i,n) for(int i=0;i<=(n);i++)36 37 #define for1(i,n) for(int i=1;i<=(n);i++)38 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)40 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)42 43 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)44 45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)46 47 #define mod 100000000748 49 using namespace std;50 51 inline int read()52 53 {54 55     int x=0,f=1;char ch=getchar();56 57     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}58 59     while(ch>=0&&ch<=9){x=10*x+ch-0;ch=getchar();}60 61     return x*f;62 63 }64 int s[maxn];65 ll  n,m,p,f[maxn],fac[maxn],inv[maxn];66 inline ll c(int n,int m)67 {68     if(n<m)return 0;69     if(n<p&&m<p)return fac[n]*inv[m]%p*inv[n-m]%p;70     return c(n/p,m/p)*c(n%p,m%p)%p;71 }72 73 int main()74 75 {76 77     freopen("input.txt","r",stdin);78 79     freopen("output.txt","w",stdout);80 81     n=read();p=read();m=min(n,p-1);82     fac[0]=1;83     for1(i,m)fac[i]=fac[i-1]*(ll)i%p;84     inv[0]=inv[1]=1;85     for2(i,2,m)inv[i]=(ll)(p/i+1)*inv[i-p%i]%p;86     for2(i,2,m)inv[i]=inv[i]*inv[i-1]%p;87     for3(i,n,1)88     {89         s[i]=s[i<<1]+s[i<<1|1]+1;90         f[i]=((i<<1)>n?1:f[i<<1])*((i<<1|1)>n?1:f[i<<1|1])%p*c(s[i]-1,s[i<<1])%p;91     }92     cout<<f[1]<<endl;93 94     return 0;95 96 }  
View Code

 

BZOJ2111: [ZJOI2010]Perm 排列计数