Problem

ARC083F

题意概要:给定 \(2n\) 个二维平面上的球,坐标分别为 \((x_i,y_i)\),并给出 \(n\) 个 \(A\)类 机器人 和 \(n\) 个 \(B\)类 机器人,其中:

  • \(A\)类 加5分 机器人分布在横坐标上,坐标依次为 \((1,0),(2,0),\cdots ,(n,0)\),触发第 \(i\) 个机器人,它会将位处第 \(i\) 列的最下头的球拿走(即横坐标为 \(i\) 且纵坐标最小的球)
  • \(B\)类 不加分 机器人分布在横坐标上,坐标依次为 \((0,1),(0,2),\cdots ,(0,n)\),触发第 \(i\) 个机器人,它会将位处第 \(i\) 行的最左侧的球拿走(即纵坐标为 \(i\) 且横坐标最小的球)

现在需要依次触发这 \(2n\) 个机器人,(每个机器人只能被触发一次),问有多少种触发机器人的方式能将所有球拿完(共 \((2n)!\) 种可能情况)

\(2\le n\le 10^5,\ 1\le x_i,y_i\le n\)

Solution

做完这道毒瘤题,17年的作业终于完成了! (。・∀・)ノ゙

往上一翻发现自己是从一半开始做的 இ皿இ

乍一看没有啥子想法

考虑到一个球 \((x,y)\),它有两种被清除的方式:被第 \(x\) 个 \(A\) 給除掉;被第 \(y\) 个 \(B\) 給除掉。而同时,由于球的数量和机器人的数量相同,所以每个机器人必须认领一个球。

这乍一看没啥子用,但放在图上就是个基环树森林:

  • 将图给构出来:对于每个球 \((x,y)\),在 \(x\) 和 \(y'\) 间连边。
  • 由于每个机器人必须认领一个球,所以可视作每个点必须认领一条边。可以发现如果这个图不是基环树森林,则整个题根本无法满足。
  • 由于每个球需要被一个机器人捡拾,所以需要给基环树森林的每条边定向,使得每个点只有一条入边(一个点的入边即它认领的边,即 “一种合法的定向方案” 对应着 “一种合法的球和机器人的匹配方式”)。
  • 为了满足题目中所描述的“机器人只会拿离自己最近的球”的限制,对于\(A\)类机器人 \((x,0)\) 去拿球 \((x,y)\),需要\(B\)类机器人将 \((x,t),t\in[1,y)\) 上的球清理干净先,所以这些 \(B\) 类 机器人需要比这个 \(A\)类机器人更早被触发。

原题转化为:对于每种给森林定向的方案,求出其满足上述拓扑关系的排列个数。


先考虑对于某种定向方案,求出合法排列方案。

如果对于这种拓扑关系连边,最终这些拓扑序关系的边将组成一个内向树森林:

  • 若负责拿取球 \((x_1,y_1)\) 机器人 是 负责拿取球 \((x_2,y_2)\) 机器人 的先决条件,则其至少需要满足 \(x_1+y_1<x_2+y_2\),这证实了整个图应该是一个 \(DAG\)。
  • 每个 \(B\)类机器人只可能是一个 \(A\)类机器人的先决条件,所以每个点只有一条出边。
  • 综上:这是一个内向树森林。

对于内向树森林求拓扑序的部分,应该都很熟悉了:设森林点集为 \(S\),节点 \(i\) 的子树大小为 \(sz_i\),则这个内向树森林的拓扑序个数为

\[\frac {|S|!}{\prod_{x\in S}sz_x}
\]

简要说一下证明:可以将Dp式列出来,将每个节点 \(x\) 在自身计算的系数 \((sz_x-1)!\) 与在其父亲 \(f\) 处计算的 \(\frac 1{sz_x!}\) 抵消,可得 \(\frac 1{sz_x}\),综合可得上述公式。森林的话,考虑拿一个虚根将所有树串起来即可。


解决完了求方案数的任务,再考虑枚举定向方案。

枚举所有定向方案肯定是不可取的,但幸运的是,这是一个基环树森林。

对于一棵基环树而言,其非环边只能由远离环的点认领,而环则有顺逆两种方式认领,可以暴力枚举。

由幼儿园学习的乘法分配率可知,不同的树之间没必要一起枚举,所以对于每棵树算出两种定向方式的答案和,再将所有树的答案乘起来即可。


时间复杂度明显是线性,顶多是枚举每棵树的两种定向方式时有个 \(2\) 的常数

Code

#include <cstdio>
#include <cctype>
typedef long long ll; template <typename _tp> inline void read(_tp&x){
char ch=getchar(),ob=0;x=0;
while(ch!='-'&&!isdigit(ch))ch=getchar();if(ch=='-')ob=1,ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();if(ob)x=-x;
} const int N = 201000;
struct Edge {int v, nxt;} a[N*4];
int head[N], Head[N], indeg[N];
int sz[N], pr[N];
bool vis[N];
int n, _; inline void add(int x, int y, int*arr) {
a[++_].v = y, a[_].nxt = arr[x], arr[x] = _;
} const int p = 1e9+7;
int fac[N], ifac[N], inv[N]; int st[N], tp;
#define FID(i) for(int id=1,i;i=st[id],id<=tp;++id) int X, Y;
int et, pt; void bfs(int x, int las) {
vis[st[++tp] = x] = true, ++pt;
for(int i=head[x];i;++et,i=a[i].nxt)
if(!vis[a[i].v]) bfs(a[i].v, x);
else if(a[i].v != las) X = x, Y = a[i].v;
} void tfs(int x, int las) {
for(int i=head[x];i;i=a[i].nxt)
if(a[i].v != las and a[i].v != X)
pr[a[i].v] = x, tfs(a[i].v, x);
} void dfs(int x, int las) {
sz[x] = 1;
for(int i=Head[x];i;i=a[i].nxt)
if(a[i].v != las)
dfs(a[i].v, x), sz[x] += sz[a[i].v];
} int solve() {
tfs(X, Y);
pr[X] = Y;
FID(i) Head[i] = indeg[i] = 0;
FID(x) for(int i=head[x];i;i=a[i].nxt)
if(a[i].v < pr[x]) add(x, a[i].v, Head), ++indeg[a[i].v]; FID(i) if(!indeg[i]) dfs(i, i);
int Ans = fac[pt];
FID(i) Ans = (ll)Ans * inv[sz[i]]%p;
return Ans;
} int main() {
read(n);
for(int i=1,x,y;i<=(n<<1);++i) {
read(x), read(y), y += n;
add(x, y, head), add(y, x, head);
} n <<= 1;
fac[0] = fac[1] = inv[0] = inv[1] = ifac[0] = ifac[1] = 1;
for(int i=2;i<=n;++i) {
fac[i] = (ll)fac[i-1] * i%p;
inv[i] = (ll)(p-p/i) * inv[p%i]%p;
ifac[i] = (ll)ifac[i-1] * inv[i]%p;
} int Ans = fac[n];
for(int i=1;i<=n;++i)
if(!vis[i]) {
tp = pt = et = 0;
bfs(i, i);
Ans = (ll)Ans * ifac[pt]%p;
if((pt << 1) != et) return puts("0"), 0;
int res = solve();
X ^= Y, Y ^= X, X ^= Y;
res += solve();
Ans = (ll)Ans * res%p;
}
printf("%d\n", Ans);
return 0;
}

题解-AtCoder ARC-083F Collecting Balls的更多相关文章

  1. [题解] Atcoder ARC 142 D Deterministic Placing 结论,DP

    题目 (可能有点长,但是请耐心看完,个人认为比官方题解好懂:P) 首先需要注意,对于任意节点i上的一个棋子,如果在一种走法中它走到了节点j,另一种走法中它走到了节点k,那么这两种走法进行完后,棋子占据 ...

  2. [题解] Atcoder ARC 142 E Pairing Wizards 最小割

    题目 建图很妙,不会. 考虑每一对要求合法的巫师(x,y),他们两个的\(a\)必须都大于\(min(b_x,b_y)\).所以在输入的时候,如果\(a_x\)或者\(a_y\)小于\(min(b_x ...

  3. [题解] Atcoder Regular Contest ARC 147 A B C D E 题解

    点我看题 A - Max Mod Min 非常诈骗.一开始以为要观察什么神奇的性质,后来发现直接模拟就行了.可以证明总操作次数是\(O(nlog a_i)\)的.具体就是,每次操作都会有一个数a被b取 ...

  4. 【题解】Atcoder ARC#96 F-Sweet Alchemy

    首先,我们发现每一个节点所选择的次数不好直接算,因为要求一个节点被选择的次数大于等于父亲被选择的次数,且又要小于等于父亲被选择的次数 \(+D\).既然如此,考虑一棵差分的树,规定每一个节点被选择的次 ...

  5. 【题解】Atcoder ARC#90 F-Number of Digits

    Atcoder刷不动的每日一题... 首先注意到一个事实:随着 \(l, r\) 的增大,\(f(r) - f(l)\) 会越来越小.考虑暴力处理出小数据的情况,我们可以发现对于左端点 \(f(l) ...

  6. 【题解】Atcoder ARC#94 F-Normalization

    再次膜拜此强题!神级性质之不可能发现系列收藏++:首先,对于长度<=3的情况,我们采取爆搜答案(代码当中是打表).对于长度>=4的情况,则有如下几条玄妙的性质: 首先我们将 a, b, c ...

  7. 【AtCoder Beginner Contest 074 B】Collecting Balls (Easy Version)

    [链接]h在这里写链接 [题意] 看懂题目之后就会发现是道大水题. [题解] 在这里写题解 [错的次数] 0 [反思] 在这了写反思 [代码] #include <bits/stdc++.h&g ...

  8. [题解] Atcoder Regular Contest ARC 148 A B C E 题解

    点我看题 题目质量一言难尽(至少对我来说 所以我不写D的题解了 A - mod M 发现如果把M选成2,就可以把答案压到至多2.所以答案只能是1或2,只要判断答案能不能是1即可.如果答案是1,那么M必 ...

  9. [题解] Atcoder Regular Contest ARC 151 A B C D E 题解

    点我看题 昨天刚打的ARC,题目质量还是不错的. A - Equal Hamming Distances 对于一个位置i,如果\(S_i=T_i\),那么不管\(U\)的这个位置填什么,对到\(S\) ...

随机推荐

  1. Unity3D ACT动作游戏《武士2》项目源码附教程

    武士二源码亲测unity2018.3.6能运行 仅供学习附有教程 教程完整73课,网上大部分一般为65课, 教程大小27GB,mp4格式 整理不易 扫码时备注或说明中留下邮箱 付款后如未回复请至htt ...

  2. Python 设计模式之建造者模式 Builder Pattern

    #引入建造者模式 肯德基的菜单上有 薯条, 鸡腿,鸡翅,鸡米花,可乐,橙汁,火腿汉堡,至尊虾汉堡,牛肉汉堡 , 鸡肉卷等这些单品,也有很多套餐. 比如 套餐1:鸡翅,至尊虾汉堡,可乐,薯条 套餐2:鸡 ...

  3. python监控rabbitmq的消息队列数量

    [root@localhost chen]# cat b.py #!/usr/bin/python # -*- coding: UTF-8 -*- import json,time import re ...

  4. ISO/IEC 9899:2011 条款6.8.2——标签语句

    6.8.2 复合语句 语法 1.compound-statement: {    block-item-listopt    } block-item-list: block-item block-i ...

  5. python中的修饰符@的作用

    1.一层修饰符 1)简单版,编译即实现 在一个函数上面添加修饰符 @另一个函数名 的作用是将这个修饰符下面的函数作为该修饰符函数的参数传入,作用可以有比如你想要在函数前面添加记录时间的代码,这样每个函 ...

  6. 阿里云服务器Svn-Server无法连接

    总结:关于阿里云服务器Svn-Server无法连接,Svn-Server的配置问题 2018年07月09日 11:51:08 周同学的博客 阅读数:355   最近在使用阿里云服务器时,SQL SER ...

  7. C++的override和final

    1.final用于让虚函数不可被重写 struct B2 { virtual void f() final {} // final 函数 }; struct D2 : B2 { virtual voi ...

  8. ABAP DEMO ALVtree显示BOM层级

    展示效果: *&---------------------------------------------------------------------* *& Report YCX ...

  9. expect 实现自动交互脚本

    1. 说明 在编写脚本时,可能会遇到需要在另一台主机上执行一个命令,或者在本机拷贝另一台主机内的一个文件.如果两台主机之间没有做互信,就会牵扯到用户输入密码的交互过程,这对编写自动脚本来说, 就行不通 ...

  10. HTML布局水平导航条1制作

    该文是用css制作个导航条,用竖线分隔,导航条是点击的多个区块.步骤:ul里设置需要数量的li,li中加上a链接给ul加样式,去掉默认的前面的点给li设置左浮动,让ul里的li横向排列a链接设置成块状 ...