版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢 https://blog.csdn.net/Deep_Kevin/article/details/83003348
正题
首先,我们先转化问题,要求,就相当于要求。
那么这就像当与一棵n个节点的完全二叉树,那么我们统计一下每棵子树的大小,然后下去更新算一下组合数就可以了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int n;
long long p;
int l[1000010];
int tot[1000010];
long long fac[1000010],fav[1000010];
void dfs(int x){
tot[x]=1;
if(x*2<=n) {
dfs(x*2);
tot[x]+=tot[x*2];
l[x]=tot[x*2];
}
if(x*2+1<=n) {
dfs(x*2+1);
tot[x]+=tot[x*2+1];
}
}
long long C(int x,int y){
return fac[x]*fav[x-y]%p*fav[y]%p;
}
long long F(int x){
if(x*2+1<=n) return F(x*2)*F(x*2+1)%p*C(tot[x]-1,l[x])%p;
else if(x*2<=n) return F(x*2);
else return 1;
}
long long ksm(long long x,long long t){
long long tot=1;
while(t>0){
if(t%2==1){
tot*=x;
tot%=p;
}
t/=2;
x*=x;
x%=p;
}
return tot;
}
long long inv(long long x){
return ksm(x,p-2);
}
int main(){
scanf("%d %lld",&n,&p);
fac[0]=1;
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%p;
fav[n]=inv(fac[n]);
for(int i=n-1;i>=1;i--) fav[i]=fav[i+1]*(i+1)%p;
dfs(1);
printf("%lld\n",F(1));
}