ARC093F Dark Horse

题意

2n 个人按照满二叉树的形态进行淘汰赛,你是 1 号,有 m 个人能打赢你,其他人都打不过你。对于其他人,编号小的人胜利。你现在要把这些人放在满二叉树的叶子上并打淘汰赛,显然一共 (2n)! 种方案。问最终胜利的人是你的方案数。

n,m16

分析

题目要求你 n 场比赛必须全赢,这比较难处理,考虑容斥,钦定若干场比赛你会输掉。当然,这种情况下即使你输了仍然会晋级。为了方便,不妨让你自己待在 1 号位置。如果某个人 i 要在第 j 轮比赛中胜出,那么你就需要在编号大于 ini 个数中选出 2j1 个炮灰。而编号越大,限制越紧,于是考虑从后往前 dp,设 fi,j 表示 [i,m] 中的人已经钦定 j 个人参加比赛的方案数,同时 j 也代表了已经钦定过的比赛编号集合,带容斥系数。转移则考虑当前是否钦定 i 胜利,若钦定则需要选出一场没钦定过的比赛 k,然后在 2naij 个炮灰中选择 2k1 个,然后让炮灰们在 2k 内部自由排序,然后乘上 1 的容斥系数:

fi,j+{k}fi+1,j(2naij2k1)(2k)!

不钦定则有 fi,jfi+1,j

计算答案时没被钦定的那些人在剩下的位置自由排序即可,有 ansf1,j(2n1j)!

最后,由于 1 可以在任何位置,而实际上 1 在哪个位置方案数都是一样的,于是答案自乘 2n 即可,复杂度 O(2nnm)

int n,m,a[maxn];
int f[maxn][maxm];
int fac[maxm],inv[maxm];
int ksm(int x,int y){
	int res=1;
	for(;y;y>>=1,x=x*x%mod)if(y&1)res=res*x%mod;
	return res;
}
int C(int x,int y){
	if(x<y)return 0;
	return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
inline void adder(int &x,int y){x+=y,x=x>=mod?x-mod:x;}
inline void suber(int &x,int y){x-=y,x=x<0?x+mod:x;}
void init(int lim){
	fac[0]=1;rep(i,1,lim)fac[i]=fac[i-1]*i%mod;
	inv[lim]=ksm(fac[lim],mod-2);per(i,lim-1,0)inv[i]=inv[i+1]*(i+1)%mod;
}
inline void solve_the_problem(){
	n=rd(),m=rd(),init(1<<n);
	rep(i,1,m)a[i]=rd();
	f[m+1][0]=1;
	per(i,m,1)rep(S,0,(1<<n)-1)if(f[i+1][S]){
		adder(f[i][S],f[i+1][S]);
		rep(j,0,n-1)if(!((S>>j)&1)){
			suber(f[i][S|(1<<j)],f[i+1][S]*C((1<<n)-a[i]-S,(1<<j)-1)%mod*fac[1<<j]%mod);
		}
	}
	int ans=0;
//	write(f[1][1],32),write(f[1][2]);
	rep(S,0,(1<<n)-1)adder(ans,f[1][S]*fac[(1<<n)-1-S]%mod);
	write((1ll<<n)*ans%mod);
}

作者:dcytrl

出处:https://www.cnblogs.com/dcytrl/p/18700270

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   dcytrl  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示