# BZOJ 2111: [ZJOI2010]Perm 排列计数 [Lucas定理]

## 2111: [ZJOI2010]Perm 排列计数

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 1936  Solved: 477
[Submit][Status][Discuss]

## Output

100%的数据中，1 ≤ ��� N ≤ 106, P��� ≤ 10^9，p是一个质数。 数据有所加强

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=1e6+5;
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int n,P;
ll fac[N];
ll Pow(ll a,int b,int P){
ll re=1;
for(;b;b>>=1,a=a*a%P)
if(b&1) re=re*a%P;
return re;
}
void iniFac(int n){
fac[0]=1;
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%P;
}
ll C(int n,int m){
return fac[n]*Pow(fac[m]*fac[n-m]%P,P-2,P)%P;
}
ll Lucas(int n,int m){
if(n<m) return 0;
ll re=1;
for(;m;m/=P,n/=P) re=re*C(n%P,m%P)%P;
return re;
}
int size[N<<1];
ll f[N<<1];
void dp(){
for(int i=n;i>=1;i--){
int l=i<<1,r=i<<1|1;
size[i]=size[l]+size[r]+1;
f[i]=Lucas(size[i]-1,size[l])*(l>n?1:f[l])%P*(r>n?1:f[r])%P;
}
printf("%lld",f[1]);
}
int main(){
freopen("in","r",stdin);
}