首页 > 其他分享 >[ARC083F] Collecting Balls

[ARC083F] Collecting Balls

时间:2024-08-23 10:29:44浏览次数:15  
标签:Collecting Balls fa int siz 200010 ARC083F vis st

My Blogs

[ARC083F] Collecting Balls

建图,连边 \((x_i,y_i+n)\),这样会形成一个基环树森林。对于基环树的每条边,需要把他归到他连接的两个点中任意一个,并且每个点只能拥有一条边。

对于每个基环树分别计算,树边归属的点一定是它两端深度较大的那个,环边归属点整体只有两种方式:顺时针和逆时针。确定了边挂在哪个点上之后,操作顺序的限制就是,如果边 \((x,y)\) 归到了点 \(y\),则要求所有 \((y,z),z<x\) 的边需要在它之前操作。

把边看成点,再建一个图来表示拓扑关系:\((x,y)\) 表示 \(x\) 需要在 \(y\) 之前进行操作。不难证明这是一个森林:对于树边之间显然只有从下到上的边,环边上的边形成了若干条单向链,还有一些环边指向树边的边,所以一定是外向树森林。

然后是非常典的外向树拓扑序计数。对于点 \(i\),自己需要放到最前面,然后儿子之间是随意排的,设 \(f_i\) 表示 \(i\) 子树内拓扑序数量,则:

\[f_i=\prod f_{to}\frac{(siz_i-1)!}{\prod siz_{to}!} \]

右边的分数是一个组合数系数,表示儿子之间可以任意排列。所以每个点的贡献恰好就是 \(\frac {1}{siz_i}\)。一个外向树森林的答案就是 \(\frac{n!}{\prod siz_i}\)。总复杂度 \(\mathcal O(n)\)。

en,sum,sz,ans=1,b[200010],fr[200010],inv[200010];
vector<pii> T[200010];
vi G[200010],ve;
int vis[200010],deg[200010],siz[200010],Id[200010];
stack<int> st;
void dfs0(int x)
{
	vis[x]=1,sz+=2,sz-=T[x].size();
	for(auto [to,v]:T[x])
	{
		ve.eb(v);
		if(!vis[to])dfs0(to);
	}
}
void dfs(int x,int fa=0)
{
	st.e(x),vis[x]=2;
	for(auto [to,v]:T[x])if(to!=fa)
	{
		if(vis[to]==2)
		{
			while(st.top()!=to)b[++len]=st.top(),st.pop();
			b[++len]=to;
			return;
		}
		else dfs(to,x);
		if(len)return;
	}
	st.pop();
}
void dfs1(int x,int fa=0,int from=0)
{
	for(auto [to,v]:T[x])if(to!=fa&&vis[to]<3)
	{
		if(to<fa)G[from].eb(v),++deg[v];
		dfs1(to,x,v);
	}
}
void dfs2(int p)
{
	siz[p]=1;
	for(auto to:G[p])dfs2(to),siz[p]+=siz[to];
	Mmul(sum,inv[siz[p]]);
}
inline void mian()
{
	read(n),fr[0]=inv[0]=1;int x,y,val,S;
	for(int i=1;i<=2*n;++i)fr[i]=Cmul(fr[i-1],i);
	inv[2*n]=power(fr[2*n],MOD-2);
	S=fr[2*n];
	for(int i=2*n-1;i>0;--i)inv[i]=Cmul(inv[i+1],i+1);
	for(int i=1;i<=2*n;++i)Mmul(inv[i],fr[i-1]);
	for(int i=1;i<=2*n;++i)read(x,y),T[x].eb(mp(y+n,i)),T[y+n].eb(mp(x,i));
	for(int i=1;i<=2*n;++i)if(!vis[i])
	{
		len=sz=0,ve.clear(),dfs0(i),sort(ve.begin(),ve.end());
		ve.resize(unique(ve.begin(),ve.end())-ve.begin());
		if(sz!=0){puts("0");return;}
		Mmul(S,power(fr[ve.size()],MOD-2));
		dfs(i),b[len+1]=b[1],b[0]=b[len];
		for(int i=1;i<=len;++i)vis[b[i]]=3;
		for(int i=1;i<=len;++i)//right
		{
			int id=-1;
			for(auto [to,v]:T[b[i]])if(to==b[i-1]){id=v;break;}
			assert(id!=-1),dfs1(b[i],b[i-1],id),Id[i]=id;
		}
		Id[len+1]=Id[1];
		for(int i=0;i<len;++i)if(b[i+2]<b[i])
		G[Id[i+1]].eb(Id[i+2]),++deg[Id[i+2]];
		sum=fr[ve.size()];
		for(auto p:ve)if(!deg[p])dfs2(p);
		for(auto p:ve)G[p].clear(),deg[p]=0;
		val=sum,sum=fr[ve.size()];
		for(int i=1;i<=len;++i)
		{
			int id=-1;
			for(auto [to,v]:T[b[i]])if(to==b[i+1]){id=v;break;}
			assert(id!=-1),dfs1(b[i],b[i+1],id),Id[i]=id;
		}
		Id[0]=Id[len];
		for(int i=0;i<len;++i)if(b[i]<b[i+2])
		G[Id[i+1]].eb(Id[i]),++deg[Id[i]];
		for(auto p:ve)if(!deg[p])dfs2(p);
		Mmul(ans,Cadd(val,sum));
	}
	write(Cmul(S,ans));
}

标签:Collecting,Balls,fa,int,siz,200010,ARC083F,vis,st
From: https://www.cnblogs.com/WrongAnswer90/p/18375448

相关文章

  • D. Ice Cream Balls
    题目链接:https://codeforces.com/contest/1862/problem/D题目:思路讲解:首先观察样例和题目不难看出,x个不重复的数字一共能组成x(x-1)/2个数组,而当有重复的数字出现的时候,就只能多组成一个数组,那思路就很明确了,先找出最多能有几个不重复的数字,之后再加上需要完成的数组和已有的数......
  • [ABC366C] Balls and Bag Query 题解
    [ABC366C]BallsandBagQuery题解题目传送门AT原题传送门首先是题面的翻译:你有一个袋子,给予\(Q\)次操作,操作有三种1\(x\),将一个写有整数\(x\)的球放入袋中。2\(x\),从袋中取出一个写有整数\(x\)的球。3,查询袋中球上的不同整数的数目。整理了一下思......
  • 题解:AT_abc366_c [ABC366C] Balls and Bag Query
    题意给你一个可重集,要求支持插入,删除,元素种类查询三种操作。分析直接乱搞,用一个桶记录每种数字的出现次数,再用一个变量\(sum\)记录元素种类数。插入的时候看看当前该元素出现次数是否为\(1\),删除的时候看看当前元素出现次数是否为\(0\),如果是的话让\(sum\)相应加减即可......
  • CF844D Boxes And Balls
    题意有\(n\)个箱子、\(n\)种颜色的球,第\(i\)种颜色的球有\(w_i\)个,最开始时都在第\(1\)个箱子中。每次可以从有球的一个箱子中拿出所有球,并随意分割为2部分或3部分,并放入箱子,需要的代价为球的总数。问将每种颜色的球都放在对应的一个箱子中需要的代价最少是多少。......
  • I Love Balls
    转换对象,考虑每个球能被A/B拿到的概率是多少(注意对于每个特殊球/非特殊球来说,能被某一人拿到的概率是相同的)然后就可以看这篇题解这篇题解的正确性在于我们不用关注当前拿球的人是谁,对于一整局游戏,无论最后球是按什么顺序拿的,概率都是相等的;这也就是说,每一局游戏的概率与“随机......
  • Collecting Numbers II
    原题链接题解首先,对于数字i如果location[i]<location[i-1]那么遍历次数需要+1,否则不变。因此,对于交换的数字x,y而言,他们只能影响x-1,x+1,y-1,y+1的遍历次数,只需要考虑有限的几种情况即可(需要特判abs(x-y)==1的情况)。code #include<bits/stdc++.h>u......
  • Collecting Numbers II
    原题链接题解如果一个\(k\),其前面没有出现过\(k-1\),那么回合数+1,我们令这样的数叫做断点因此交换两个数\(l,r\)不会影响\([1,l-1],[r+1,n]\)内的断点code#include<bits/stdc++.h>#definelllonglong#definelowbit(x)((x)&(-x))usingnamespacestd;constll......
  • CF1983E I Love Balls
    题意\(n\)个小球,有\(k\)个特殊小球,两个人轮流随机拿,每个小球有权值,如果拿到特殊球就再拿一个,问两个人的期望得分。题解关键1如果没有特殊小球,那么每个球是等价的,计算期望的时候可以直接用平均值作为一个小球的权值,把每个小球的权值都看成平均值关键2把拿取操作看成一个序......
  • CF1983E I Love Balls
    Problem-E-Codeforces爱丽丝和鲍勃玩摸球游戏。有\(n\)个球,其中\(k\)个是特殊球。每个球都有其价值。他们轮流且不放回地摸球,每回合随机摸一个球并获得该球的价值。特别地,如果摸到了特殊球(且至少还有一个球)则这名玩家继续摸球。如果摸到的是普通球,则换人摸球。这样轮流......
  • C. Tenzing and Balls
    链接:https://codeforces.com/problemset/problem/1842/Corhttps://www.luogu.com.cn/problem/CF1842C大概的思路就是利用dp[i]记录前i个数据最多消掉的数字个数,然后对∀j:a[i]==a[j]&&j<i进行dp[i]=dp[j-1]+i-j+1的递推优化:代码:#define_CRT_SECURE_NO_WARNI......