ABC321G

其实赛时可能可以做出来的,只是打了前 6 道想下班了,有点小小遗憾。

首先问题看起来很唬人,考虑转换一下。考虑已经固定 m 条边,对于一个集合 S,什么时候会不与其他点有边。容易发现,此时需要满足 [RiS]=[BjS]。记这个数为 cS。但是这还不够,因为 S 中点连边方案数还没有计算。

这个答案显然不是 cS!。因为 S 可能可以分成两个集合 s,t 都满足上述条件,则会重复计算。考虑如何去重。设 dps 为集合 S 的答案。我们钦定 t 包含 S 里最小的元素,则有 dps=cs!tSdpt×(csct)!

然后怎么办呢?

作者表示再做一遍 dp,O(m3m) 解决。还真过了。

但是事实上 ans=dps×(mcs)!。解决。

code:

点击查看代码
int n,m,e[23],d[23],f[N],g[N],h[N],c[N];
il int Mod(int x,int y){return x+y>=mod?x+y-mod:x+y;}
il int lowbit(int x){return x&(-x);}
il int qpow(int x,int y){
	int ret=1;
	while(y){
		if(y&1)ret=1ll*ret*x%mod;
		x=1ll*x*x%mod;y>>=1;
	}
	return ret;
}
void Yorushika(){
	scanf("%d%d",&n,&m);
	f[0]=1;
	rep(i,1,m){
		int x;scanf("%d",&x);
		e[x]++;
		f[i]=1ll*f[i-1]*i%mod;
	}
	rep(i,1,m){
		int x;scanf("%d",&x);
		d[x]++;
	}
	const int k=1<<n;
	int ans=0;
	rep(i,1,k-1){
		rep(j,0,n-1){
			g[i]+=e[j+1]*(i>>j&1);
			h[i]+=d[j+1]*(i>>j&1);
		}
		if(g[i]!=h[i])
			continue;
		c[i]=f[g[i]];
		for(int j=(i-1)&i;j;j=(j-1)&i){
			if(g[j]!=h[j]||lowbit(i)!=lowbit(j))
				continue;
			c[i]=Mod(c[i],mod-1ll*c[j]*f[g[i]-g[j]]%mod);
		}
		ans=Mod(ans,1ll*c[i]*f[m-g[i]]%mod);
	}
	printf("%lld\n",1ll*ans*qpow(f[m],mod-2)%mod);
}
signed main(){
	int t=1;
	//	scanf("%d",&t);
	while(t--)
		Yorushika();
}
posted @   yinhee  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示