2 条题解
-
3
因为我们发现第 号位置上的人只对 号位置的人和 的位置上的人有影响,这很像二叉树
所以说我们可以考虑建树,使得每个节点都小于自己的儿子节点即可
然后我们考虑对每一个节点来看有多少种可能性的填法,最后乘起来即可
首先根节点一定要填
然后我们考虑左子树,左子树的所有数的选择方案是 ,也就是说在剩下的 个数里面,选择 号节点的子树大小个数的方案数
然后依次往下递归,对每一个左子树的节点附上一个这样的值看,最后乘起来就行了
#include<iostream> #include<cstdio> #define int long long using namespace std; bool Test_MLE_start; const int N=2e6+10; int T=1,n,mod,ans=1; int fac[N],inv[N],ret[N],sz[N],fa[N]; inline int reads(){ char c=getchar(); int sum=0,f=1; while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ sum=(sum<<3)+(sum<<1)+(c^'0'); c=getchar(); } return sum*f; } inline void files(){ freopen("std.in","r",stdin); freopen("std.out","w",stdout); } inline void clr(){ // Don't forget! } int C(int n,int m){ if(n<m) return 0; return fac[n]*inv[m]%mod*inv[n-m]%mod; } int Lucas(int n,int m){ if(!m) return 1; return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod; } void dfs(int idx){ if(idx>n) return; dfs(2*idx),dfs(2*idx+1); fa[2*idx]=fa[2*idx+1]=idx; sz[idx]+=sz[2*idx]+sz[2*idx+1]+1; } void dfs2(int idx){ if(idx>n) return; if(idx%2==0){ ret[idx]=Lucas(sz[fa[idx]]-1,sz[idx]); // cout<<idx<<":"<<fa[idx]<<" "<<sz[fa[idx]]-1<<" "<<sz[idx]<<"\n"; } dfs2(idx*2),dfs2(idx*2+1); } bool Test_MLE_end; signed main(){ // printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0); // files(); // T=reads(); while(T--){ clr(); n=reads(),mod=reads(); inv[0]=inv[1]=fac[0]=fac[1]=1; for(int i=2;i<=N-10;i++) fac[i]=fac[i-1]*i%mod,inv[i]=(mod-mod/i)*inv[mod%i]%mod; for(int i=1;i<=N-10;i++) inv[i]=inv[i]*inv[i-1]%mod; for(int i=1;i<=n;i++) ret[i]=1; dfs(1); dfs2(1); for(int i=1;i<=n;i++) ans=(ans*ret[i])%mod; printf("%lld\n",ans); } return 0; } -
0
容易发现二叉树。
因为答案只和相对大小有关,所以对于一个子树,给它分配那些点的方案数都是相同的,于是自底向上dp方案数。
#include<bits/stdc++.h> #define int long long #define lc (x<<1) #define rc (x<<1|1) using namespace std; const int N=1e6+17; int mod,siz[N],dep[N],mxd; int mul[N],inv[N]; int qpow(int a,int b){ int res=1; while(b){ if(b&1) res=res*a%mod; a=a*a%mod;b=b>>1ll; }return res; } int C(int n,int m){ if(n<m) return 0; int res=mul[n]*inv[m]%mod; res=res*inv[n-m]%mod;return res; } int Lucas(int n,int m){ if(n<mod&&m<mod) return C(n,m); return (int)(C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod); } int n; void dfs1(int x){ siz[x]=1; if(lc<=n){dfs1(lc);siz[x]+=siz[lc];} if(rc<=n){dfs1(rc);siz[x]+=siz[rc];} } int dfs(int x){ if(lc>n||rc>n) return 1;// int res=dfs(lc)*dfs(rc)%mod; res=res*Lucas(siz[x]-1,siz[lc])%mod; return res; } signed main(){ cin >> n >> mod;mul[0]=1;inv[0]=1; for(int i=1;i<=N-1;i++){ mul[i]=mul[i-1]*i%mod; inv[i]=qpow(mul[i],mod-2); }dfs1(1);int ans=dfs(1); cout << ans << '\n'; return 0; }
- 1
信息
- ID
- 235
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- (无)
- 递交数
- 25
- 已通过
- 11
- 上传者