根据题目所给信息,要求所有
2<=i<=N
时,满足
Pi>Pi/2
列一下,就是:
p2>p1
,
p3>p1
,
p4>p2
,
p5>p2
,
p6>p3
,
p7>p3
发现很像一颗二叉树!就是一颗二叉树。。
满足根节点小于两个儿子节点。
然后显然有子结构,可以
dp
对于一颗以
i
为根的子树,令
f[i]=f[l]∗f[r]∗Csz[l]sz[i]−1
以
i
为子树共有
然而
p
可能大于
预处理只用预处理到
min(n,p−1)
即可。因为显然这之后的用不到啊。。
当然也可以不用预处理逆元每次直接费马小定理算,但是阶乘是需要预处理的。
【代码】
线性预处理逆元 424ms
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 1000001
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,mod;
int f[N],Fac[N],sz[N],Inv[N];
int Lucas(int x,int y)
{
if(x<y) return 0;
if(x<mod&&y<mod) return 1LL*Fac[x]*Inv[y]%mod*Inv[x-y]%mod;
return 1LL*Lucas(x/mod,y/mod)*Lucas(x%mod,y%mod)%mod;
}
int main()
{
n=read(),mod=read();Fac[0]=1;f[n+1]=1;Inv[1]=Inv[0]=1;int mx=min(n+1,mod);
for(int i=1;i<mx;i++) Fac[i]=1LL*Fac[i-1]*i%mod;
for(int i=2;i<mx;i++) Inv[i]=1LL*(mod-mod/i)*Inv[mod%i]%mod;
for(int i=1;i<mx;i++) Inv[i]=1LL*Inv[i]*Inv[i-1]%mod;
for(int i=n;i;i--)
{
static int l,r;l=i<<1,r=i<<1|1;
l=min(l,n+1),r=min(r,n+1);
sz[i]=sz[l]+sz[r]+1;
f[i]=1LL*f[l]*f[r]%mod*Lucas(sz[i]-1,sz[l])%mod;
}
printf("%d\n",f[1]);
return 0;
}
不预处理直接计算逆元 2048ms
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 1000001
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,mod;
int f[N],Fac[N],sz[N];
int Qpow(int x,int y)
{
int rtn=1;
while(y){
if(y&1) rtn=1LL*x*rtn%mod;
x=1LL*x*x%mod;y>>=1;
}
return rtn;
}
int Lucas(int x,int y)
{
if(x<y) return 0;
if(x<mod&&y<mod) return 1LL*Fac[x]*Qpow(1LL*Fac[y]*Fac[x-y]%mod,mod-2)%mod;
return 1LL*Lucas(x/mod,y/mod)*Lucas(x%mod,y%mod)%mod;
}
int main()
{
n=read(),mod=read();Fac[0]=1;f[n+1]=1;
for(int i=1;i<N;i++) Fac[i]=1LL*Fac[i-1]*i%mod;
for(int i=n;i;i--)
{
static int l,r;l=i<<1,r=i<<1|1;
l=min(l,n+1),r=min(r,n+1);
sz[i]=sz[l]+sz[r]+1;
f[i]=1LL*f[l]*f[r]%mod*Lucas(sz[i]-1,sz[l])%mod;
}
printf("%d\n",f[1]);
return 0;
}