[AGC012D]Colorful Balls

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[AGC012D]Colorful Balls相关的知识,希望对你有一定的参考价值。

题意:有$N$个球,有颜色$c_i$,重量$w_i$,若($c_a=c_b$且$w_a+w_b\leq X$)或($c_a\ne c_b$且$w_a+w_b\leq Y$),可以交换$a,b$,求总共可以得到多少种不同的颜色序列

 

首先我们当然要比较快地找到哪些球是可以交换的

因为交换具有传递性,所以我们构造一个图:若$i$和$j$可以交换,他们之间有至少一条路径

先看颜色相同

设$m_i$表示颜色为$i$的球中重量最小的球

那么对于每一个球$k$,只需要考虑$w_k+w_{m_{c_k}}\leq X$即可,因为所有球都与最轻的相连,他们也就自然连通了

再看颜色不同

设$m_i$中重量最小的球为$a$,重量次小的球为$b$

那么对于每一个球$k$,只需要考虑$w_k+w_a\leq Y$或$w_k+w_b\leq Y$即可

证明:对于任意$s,t(w_s+w_t\leq Y)$

若$c_s\ne c_a$且$c_t\ne c_a$,交换方式:$s\Leftrightarrow a\Leftrightarrow t$

若$c_s\ne c_b$且$c_t\ne c_b$,交换方式:$s\Leftrightarrow b\Leftrightarrow t$

若$\{c_s,c_t\}=\{c_a,c_b\}$,交换方式:$s\Leftrightarrow a\Leftrightarrow b\Leftrightarrow t$

于是我们得到哪些球可以随意交换,现在要算方案数

若有$m$种颜色,第$i$种颜色的数量为$v_i$

我们按顺序把每种颜色gay进去

轮到第$i$种颜色时,有$v_i+\cdots+v_m$个空位,方案数为$C_{v_i}^{v_i+\cdots+v_m}$

于是总方案数为$C_{v_1}^{v_1+\cdots+v_m}\cdot C_{v_2}^{v_2+\cdots+v_m}\cdot\cdots\cdot C_{v_m}^{v_m}$

都是$n$的级别,直接预处理阶乘暴力算即可

#include<stdio.h>
#define mod 1000000007ll
#define inf 2147483647ll
#define ll long long
struct edge{
	int to,nex;
}e[3000010];
int c[200010],h[200010],pos[200010],cnt[200010],tot;
ll w[200010],fac[200010],rfac[200010],min[200010];
bool v[200010];
ll pow(ll a,ll b){
	ll ans=1,base=a;
	while(b){
		if(b&1)ans=(ans*base)%mod;
		base=(base*base)%mod;
		b>>=1;
	}
	return ans;
}
ll C(ll n,ll k){
	return(((fac[n]*rfac[n-k])%mod)*rfac[k])%mod;
}
void add(int a,int b){
	tot++;
	e[tot].to=b;
	e[tot].nex=h[a];
	h[a]=tot;
}
void dfs(int x){
	v[x]=1;
	for(int i=h[x];i;i=e[i].nex){
		if(!v[e[i].to])dfs(e[i].to);
	}
}
int main(){
	int n,i,fir,sec=0;
	ll X,Y,min1,min2,tot,ans;
	scanf("%d%lld%lld",&n,&X,&Y);
	fac[0]=1;
	for(i=1;i<=n;i++){
		scanf("%d%lld",c+i,w+i);
		fac[i]=(i*fac[i-1])%mod;
		min[i]=inf;
	}
	rfac[n]=pow(fac[n],mod-2);
	for(i=n;i>0;i--)rfac[i-1]=(i*rfac[i])%mod;
	for(i=1;i<=n;i++){
		if(w[i]<min[c[i]]){
			min[c[i]]=w[i];
			pos[c[i]]=i;
		}
	}
	for(i=1;i<=n;i++){
		if(i!=pos[c[i]]&&w[i]+min[c[i]]<=X){
			add(i,pos[c[i]]);
			add(pos[c[i]],i);
		}
	}
	min1=min2=inf;
	for(i=1;i<=n;i++){
		if(w[i]<min1){
			min1=w[i];
			fir=i;
		}
	}
	for(i=1;i<=n;i++){
		if(w[i]<=min2&&c[i]!=c[fir]){
			min2=w[i];
			sec=i;
		}
	}
	for(i=1;i<=n;i++){
		if(i==fir)continue;
		if(c[i]!=c[fir]&&w[i]+w[fir]<=Y){
			add(i,fir);
			add(fir,i);
		}
		if(sec&&c[i]!=c[sec]&&w[i]+w[sec]<=Y){
			add(i,sec);
			add(sec,i);
		}
	}
	dfs(fir);
	tot=0;
	for(i=1;i<=n;i++){
		if(v[i]){
			tot++;
			cnt[c[i]]++;
		}
	}
	ans=1;
	for(i=1;i<=n;i++){
		if(cnt[i]){
			ans=(ans*C(tot,cnt[i]))%mod;
			tot-=cnt[i];
		}
	}
	printf("%lld",ans);
}

以上是关于[AGC012D]Colorful Balls的主要内容,如果未能解决你的问题,请参考以下文章

[agc016b]Colorful Hats 分类讨论

[agc016b]colorful hats

AGC 016B.Colorful Hats(思路)

hdu 6035(Colorful Tree)

hdu 6035(Colorful Tree)

gym/102253C Colorful Tree 树上计数