题目大意:magic数列当且仅当2<=i<=N时,Pi>Pi/2,求magic数列数量
题解:第一项为1,把i的两个儿子看做i*2和i*2+1,这样就形成了一颗以1为根的有根树,然后按照小根堆填就好了,变成求堆的数量
f[i]=C(s[i]−1,s[l])∗f[l]∗f[r]
NOTICE:这个P是输入的,可能n>p导致p|n从而np不互质,求组合数不能直接用逆元,要用lucas定理
我的收获:逆元,逆元……
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define M 1001001
typedef long long ll;
ll n,P,size[M<<1],f[M];
ll fac[M]={1,1},I[M]={1,1},inv[M]={1,1};
void Linear_Shaker()
{
for(int i=2;i<=n;i++){
fac[i]=fac[i-1]*i%P;
I[i]=(P-P/i)*I[P%i]%P;
inv[i]=inv[i-1]*I[i]%P;
}
}
ll C(ll x,ll y)
{
if(x<y) return 0;
if(x<P&&y<P)
return fac[x]*inv[y]%P*inv[x-y]%P;
return C(x/P,y/P)*C(x%P,y%P)%P;
}
void work()
{
for(int i=n;i>=1;i--)
{
size[i]=size[i<<1]+size[i<<1|1]+1;
f[i]=C(size[i]-1,size[i<<1])*((i<<1)>n?1:f[i<<1])%P*((i<<1|1)>n?1:f[i<<1|1])%P;
}
cout<<f[1]<<endl;
}
void init()
{
cin>>n>>P;
Linear_Shaker();
}
int main()
{
init();
work();
return 0;
}