Arc083_F Collecting Balls
题目大意
给定$N$,在$(1,0),(2,0)......(N,0)$和$(0,1),(0,2)...(0,N)$上都有$1$个机器人,同时给定$2N$个坐标$(x,y),x,y\in[1,N]$上有障碍,你每次可以选择一个没有被选过的机器人$K$,若$X_K=0$,则它会沿着$y$轴正方向移动直到遇到遇到障碍或移出边界$[0,N]$,若它遇到障碍,则它会和障碍一同消失。
求选择$2N$个机器人的$(2N!)$中顺序中,有多少种会使得所有障碍消失。
题解
神仙题
考虑把每一行和每一列看做$2N$个点,对于障碍$(x,y)$,视为在$x$行$y$列之间连一条边。
显然,一条边只能被它的两个端点删掉,同一,一个点端点只能用于删掉一个条边。
那么对于每一个连通块,当且仅当它是一个基环树时才可能有解。
考虑树边,显然叶子节点只能删掉连接它的边,那么同理可得树边只能被距离环更远的端点删掉。
而环上的边也只有两种情况,每个点要么顺时针删去下一条边,要么逆时针删去下一条边,枚举即可。
假设我们已经确定了每个点删掉了哪条边。
假设我们用$x$点删掉了$(x,y)$,那么考虑$y$是$(x,y)$的另一维坐标,那么对于$x$连接的$k$,若$k<y$,删除$(x,y)$之前一定要先删除$(x,k)$,所以$k$一定要在$x$之前先选,可以再建一个图,新图中$k$向$x$连边。
于是我们就得到了一个有先后顺序要求的拓扑图。显然这是一个森林,因为对于任意点对$(a,b)$,一定不会存在两种方式从$a$到达$b$,而且新图上的边在原图中一定是从树枝的叶子一步步连向环的某一个节点,所以森林是若干颗内向树构成的。
考虑有$m$个点的内向树有多少种拓扑序。共有$m!$中排序方式,其中对于以$x$为根的子树,它可能是拓扑序当且仅当它是这$Size_x$个节点中($Size_x$表示其子树大小)的最后一个(在外向树中应该是第一个,所以有向树在去掉方向后同构则拓扑序数量),那么它是有效的序列只有$\frac{1}{Size_x}$种,每一棵子树可以独立考虑,所以拓扑序方案数就是$\frac{m!}{\prod\limits_{x=1}^{m} Size_x}$。
对于一棵内向树森林,则$Size$定义不变,$m$变为森林中所有点的点数。
由于环上的选边方式有两种,就枚举方向再加起来,就得到了消完这个连通块的方案数。
对于连通块$i$,设其点数为$m_i$,方案数为$Ans_i$,一共有$K$个连通块。
最后的总方案数是$$\prod\limits_{i=1}^{K}\dbinom{\sum\limits_{j=i}^{K}m_j}{m_i}\times Ans_i$$
虽然已经可以算了,但是我们还可以通过把$\dbinom{n}{m}$化为$\frac{n!}{m!(n-m)!}$的形式,不难发现这个上式就变成了$$\frac{(2N)!}{\prod\limits_{i=1}^{K}m_i}\prod\limits_{i=1}^{K}Ans_i$$更加直观且容易计算。
复杂度$O(n)$。
#include<bits/stdc++.h>
#define LL long long
#define M 200020
#define mod 1000000007
using namespace std;
namespace IO{
const int BS=(1<<22)+5; int Top=0;
char Buffer[BS],OT[BS],*OS=OT,*HD,*TL,SS[20]; const char *fin=OT+BS-1;
inline char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return (HD==TL)?EOF:*HD++;}
inline void write(int x){
if(!x){putchar('0');return;} if(x<0) x=-x,putchar('-');
while(x) SS[++Top]=x%10,x/=10;
while(Top) putchar(SS[Top]+'0'),--Top;
}
inline int read(){
int nm=0; char cw=Getchar(); for(;!isdigit(cw);cw=Getchar());
for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0'); return nm;
}
}
using namespace IO;
#define mul(x,y) (LL)(x)*(y)%mod
#define upd(x,y) x=((x)+(y)>=mod)?(x)+(y)-mod:(x)+(y)
int n,m,fs[M],nt[M<<1],to[M<<1],tmp,ans=1,EG,top,ind[M],node[M];
int S[M],c[M],fa[M],nxt[M],fst[M],tar[M],cur,cnt,sz[M],inv[M],vis[M];
inline void link(int x,int y){
nt[tmp]=fs[x],fs[x]=tmp,to[tmp++]=y;
nt[tmp]=fs[y],fs[y]=tmp,to[tmp++]=x;
}
inline void edge(int x,int y){nxt[cur]=fst[x],fst[x]=cur,tar[cur++]=y;}
void init(int x,int last){
node[++cnt]=x,S[++top]=x,ind[x]=1,S[top+1]=0;
for(register int i=fs[x];~i;i=nt[i],EG++){
if(to[i]==last) continue;
if(!ind[to[i]]){init(to[i],x);continue;}
if(m) continue;
while(S[top+1]!=to[i]) vis[c[++m]=S[top--]]=true; c[0]=to[i];
} top--,ind[x]=2;
}
void build(int x,int last){
for(register int i=fs[x];~i;i=nt[i]){
if(vis[to[i]]||to[i]==last) continue;
fa[to[i]]=x,build(to[i],x);
}
}
int dfs(int x){
if(sz[x]) return 1; int res=sz[x]=1;
for(register int i=fst[x];i!=-1;i=nxt[i]){
res=mul(res,dfs(tar[i])),sz[x]+=sz[tar[i]];
} return mul(res,inv[sz[x]]);
}
inline int calc(){
for(int i=1;i<=cnt;i++) fst[node[i]]=-1,sz[node[i]]=0; cur=0; int res=1;
for(int x=1;x<=cnt;x++) for(register int i=fs[node[x]];i!=-1;i=nt[i]) if(to[i]<fa[node[x]]) edge(node[x],to[i]);
for(int x=1;x<=cnt;x++) if(!sz[node[x]]) res=mul(res,dfs(node[x])); return res;
}
inline int solve(int x){
top=0,init(x,0); if(EG!=(cnt<<1)) puts("0"),exit(0);
for(int i=1;i<=m;i++) build(c[i],0); int res=0;
for(int i=1;i<=m;i++) fa[c[i-1]]=c[i]; upd(res,calc());
for(int i=1;i<=m;i++) fa[c[i]]=c[i-1]; upd(res,calc());
return res;
}
int main(){
n=read(),ans=inv[1]=1,memset(fs,-1,sizeof(fs));
for(int i=2;i<=(n<<1);i++) ans=mul(ans,i),inv[i]=mul(inv[mod%i],mod-(mod/i));
for(int i=1;i<=(n<<1);i++) link(read()+n,read());
for(int i=1;i<=(n<<1);i++) if(!ind[i]) cnt=m=EG=0,ans=mul(ans,solve(i));
printf("%d\n",ans); return 0;
}
Arc083_F Collecting Balls的更多相关文章
- [ARC083F] Collecting Balls [建二分图+环套树定向+建拓扑图+树的拓扑序计数]
题面 [传送门](https://arc083.contest.atcoder.jp/tasks/arc083_d) 思路 这是一道真正的好题 第一步:转化模型 行列支配类的问题,常见做法就是把行和列 ...
- 【AtCoder Beginner Contest 074 B】Collecting Balls (Easy Version)
[链接]h在这里写链接 [题意] 看懂题目之后就会发现是道大水题. [题解] 在这里写题解 [错的次数] 0 [反思] 在这了写反思 [代码] #include <bits/stdc++.h&g ...
- 题解-AtCoder ARC-083F Collecting Balls
Problem ARC083F 题意概要:给定 \(2n\) 个二维平面上的球,坐标分别为 \((x_i,y_i)\),并给出 \(n\) 个 \(A\)类 机器人 和 \(n\) 个 \(B\)类 ...
- [ARC083]Collecting Balls
Description 有一个 \(n\times n\) 的矩阵,矩阵内有 \(2n\) 个球.对于 \(i \in [1,n]\) ,\((0,i) (i,0)\) 的位置各有一个启动后往右走/往 ...
- [atARC083F]Collecting Balls
考虑一个构造,对于坐标$(x,y)$,连一条$x$到$y$的边(注意:横坐标和纵坐标即使权值相同也是不同的点),之后每一个连通块独立,考虑一个连通块内部: 每一个点意味着一次删除操作,每一个边意味着一 ...
- Atcoder 乱做
最近感觉自己思维僵化,啥都不会做了-- ARC103 F Distance Sums 题意 给定第 \(i\) 个点到所有点的距离和 \(D_i\) ,要求构造一棵合法的树.满足第 \(i\) 个点到 ...
- 【AtCoder】ARC083
C - Sugar Water 计算一下可以达到水是多少,可以到达的糖是多少 枚举水,然后加最多能加的糖,是\(min(F - i *100,E * 100)\),计算密度,和前一个比较就行 #inc ...
- AtCoder刷题记录
构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...
- POJ2096 Collecting Bugs
Time Limit: 10000MS Memory Limit: 64000K Total Submissions: 5090 Accepted: 2529 Case Time Limit: ...
随机推荐
- mysql只能连接localhost解决
grant all privileges on *.* to 'root'@'%' identified by 'root';flush privileges;
- DP专题(不定期更新)
1.UVa 11584 Partitioning by Palindromes(字符串区间dp) 题意:给出一个字符串,划分为若干字串,保证每个字串都是回文串,同时划分数目最小. 思路:dp[i]表示 ...
- UI设计中的各种小控件
xib支持图形化操作,提供了几乎所有的控件可供选择,只需拖动到相应的位置即可,但是控件的后台代码仍然需要手动编写,一定程度上加速了前台的开发. xib快速开发程序,手写代码速度比较慢 xib适合做静态 ...
- 学好 Python 的 11 个优秀资源
Python是目前最流行.最易学最强大的编程语言之一,无论你是新手还是老鸟,无论是用于机器学习还是web开发(Pinterest就是案例),Python都是一件利器.此外,Python不但人气日益高涨 ...
- 【转载】格式化存储装置成为 Ext2/Ext3/Ext4 档案系统
格式化 用系统管理员帐户 (即 root) 身份打「mkfs -t ext2|ext3|ext4 储存装置」: mkfs -t ext3 /dev/sdb5 要格式化档案系统为 Ext2,亦可以直接使 ...
- 测试连接oracle数据库耗时
maven项目 主程序:ConnOracle.java package org.guangsoft.oracle; import java.sql.Connection; import java.sq ...
- INSPIRED启示录 读书笔记 - 第34章 恐惧、贪婪、欲望
消费者购买产品大多源于情感需求 企业级消费者出于恐惧和贪婪购买产品:如果不买这款产品,竞争对手会超过我,黑客会攻破我的防火墙,客户将弃我而去:如果买了,会赚得更多,省得更多 大众消费者购买产品的原因更 ...
- CentOS 7防火墙设置开放80端口
在CentOS 6.x版本中,默认使用的是iptables防火墙.到了CentOS 7.x版本,默认防火墙变成了firewalld.本篇通过使用firewalld开启.关闭 HTTP(80)端口,来讲 ...
- Optional int parameter 'time' is present but cannot be translated into a null value due to being decla
今天在操作redis的时候报了这个错:Optional int parameter 'time' is present but cannot be translated into a null val ...
- Spark-运行时架构
Spark运行时架构 在分布式环境下,Spark集群采用的时主/从结构.在一个Spark集群中,有一个节点负责中央协调,调度各个分布式工作节点.这个中央协调节点被称为驱动器(Driver),与之对应的 ...