[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的主要内容,如果未能解决你的问题,请参考以下文章