UOJ #76 【UR #6】懒癌
确实是一道很不错的题啊。
题意
感觉也没什么特别简洁的版本,大家直接看题面吧。
题解
我第一次看到这个类似问题的背景是疯狗,因此下面的题解不自觉的代入了...大家明白意思就好。
我们考虑对于疯狗,我们将其染为黑点,否则是白点。这样我们就可以用一张每个点有两种颜色的有向图来表示当前的状态。来想一想状态之间是如何转移的。
首先我们可以对每一个疯狗的主人分开考虑,计算他什么时候会发现自己的狗是疯狗,对所有的答案取\(\min\)即可。对于一个疯狗的主人,他自己能观察到的点的状态已经被确定了。于是他可以在自己的狗不疯的假设下,枚举所有他看不见的狗的状态,取其中最大的时间。可以发现状态向下的转移和这个人不能观察的人更加有关系,于是我们考虑将原图取反,在原图的补图上解决问题。此时\(i\)到\(j\)有边的意思是\(i\)不能观察\(j\)。当当前的时间等于最大时间\(+1\)时,他就会发现自己的狗是疯狗了。
那么首先要考虑的问题是怎么判断一个状态是否会永远发现不了疯狗。那么比较显然应该是转移出现了环的时候。那么什么样的图的转移会成环呢?我们假设图中有一个黑点,它可以到达图中的一个环,那么我们在转移的时候显然有一种转移是不断的把接近这个环的后继染黑,直到走到环上,接下来沿着环染黑,那么转移就会无休无止了。更准确的说,当存在一个黑点能够到达一个点数大于\(1\)的强连通分量时,就永远发现不了疯狗了。
于是我们可以发现所有能到达点数大于\(1\)的强连通分量的点都是不可以是疯狗的!那么我们就不用管这些点了。剩下的点组成了一张\(DAG\)!
于是我们只需要考虑一张每个点有两种颜色的\(DAG\)的答案就好了。这里给出一个结论:一个状态的枪响时间是所有黑点能到达的点的数目。
证明我们采用归纳法:假设对于一个状态,它能转移到的所有状态都符合这个结论了。那么我们依次考虑每个黑点,它可以将它的后继中的任意个染黑然后自己变白(当然要满足图中至少一个黑点),这样之后转移得到的答案是新的点集能到达的点数。那么由于它想要的是最大值,不难发现将所有后继染黑一定是最优的。此时除了它本身以外,它所能到达的点依然可以到达。也就是说,假如当前的其它黑点中有能够到达它的点,那么这个点的答案就是当前点集能到达的点数\(+1\),这里的加一是因为之前所说的需要多一天时间发现,否则就不加一,因为它本身已经无法到达了。
而我们需要的是所有点的答案的最小值,不难发现点集中一定有一个黑点是其它黑点无法到达的(比如拓扑序最大的点),因此“当前点集能到达的点数”这个下界总是可以取到。于是结论就成立了。
那么考虑怎么求第一问的答案。可以每个点分开算贡献。我们先用\(O(\frac{n^3}{w})\)的时间用\(\rm bitset\)求出对于每一个点能到达它的点的数目。那么对于一个点集,它会记录这个点的情况只有点集中有能到它的点。我们用所有方案减去不存在能到它的点的方案即可。
至于第二问,不难发现是求每个状态有多少点可以取到最小值。根据之前的分析,应该是不能被点集中除自己外的点到达的那些点。分开算到每个点中,就是仅包含自己和不能到自己的点的那些点集。
代码:
#include<cstdio>
#include<bitset>
#include<stack>
using std::bitset;
using std::stack;
const int mod=998244353;
inline int add(int a,int b)
{
return (a+=b)>=mod?a-mod:a;
}
inline int sub(int a,int b)
{
return (a-=b)<0?a+mod:a;
}
inline int mul(int a,int b)
{
return (long long)a*b%mod;
}
inline int qpow(int a,int b)
{
int res=1;
for(;b;a=mul(a,a),b>>=1)
if(b&1)
res=mul(res,a);
return res;
}
const int N=3005;
int n,ans,idx,cnt;
char s[N];
int g[N][N];
int dfn[N],low[N],com[N];
int size[N];
int g2[N][N];
stack<int> st;
bool inst[N];
bitset<N> from[N];
void dfs(int x)
{
register int i;
dfn[x]=low[x]=++idx;
st.push(x);inst[x]=1;
for(i=1;i<=n;i++)
if(g[x][i])
{
if(!dfn[i])
{
dfs(i);
if(low[i]<low[x])
low[x]=low[i];
}
else if(inst[i]&&dfn[i]<low[x])
low[x]=i;
}
if(dfn[x]==low[x])
{
com[x]=++cnt;size[cnt]=1;
while(st.top()!=x)
com[st.top()]=cnt,size[cnt]++,inst[st.top()]=0,st.pop();
inst[x]=0;st.pop();
}
return;
}
signed main()
{
register int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%s",s+1);
for(j=1;j<=n;j++)
if(i!=j&&s[j]=='0')
g[i][j]=1;
}
for(i=1;i<=n;i++)
if(!dfn[i])
dfs(i);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(g[i][j]&&com[i]!=com[j])
g2[com[i]][com[j]]=1;
for(i=1;i<=cnt;i++)
for(j=1;j<i;j++)
if(g2[i][j]&&size[j]>size[i])
size[i]=size[j];
int cc=0;
for(i=1;i<=cnt;i++)
if(size[i]==1)
cc++;
// for(i=1;i<=cnt;i++)
// if(size[i]==1)
// {
// to[i].set(i);
// for(j=1;j<i;j++)
// if(size[j]==1&&g2[i][j])
// to[i]|=to[j];
// }
for(i=cnt;i>=1;i--)
if(size[i]==1)
{
from[i].set(i);
for(j=cnt;j>i;j--)
if(size[j]==1&&g2[j][i])
from[i]|=from[j];
}
for(i=1;i<=cnt;i++)
if(size[i]==1)
ans=add(ans,mul(sub(qpow(2,from[i].count()),1),qpow(2,cc-from[i].count())));
printf("%d ",ans);
ans=0;
for(i=1;i<=cnt;i++)
if(size[i]==1)
ans=add(ans,qpow(2,cc-from[i].count()));
printf("%d\n",ans);
return 0;
}
UOJ #76 【UR #6】懒癌的更多相关文章
- 【UOJ#76】【UR #6】懒癌(动态规划)
[UOJ#76][UR #6]懒癌(动态规划) 题面 UOJ 题解 神....神仙题. 先考虑如果是完全图怎么做... 因为是完全图,所以是对称的,所以我们只考虑一个有懒癌的人的心路历程. 如果只有一 ...
- UOJ #76 -【UR #6】懒癌(思维题)
UOJ 题面传送门 神仙题. orz czx,czxyyds 首先没有懒癌的狗肯定不会被枪毙,证明显然. 接下来考虑怎样计算一种局面的答案,假设 \(dp_S\) 表示对于有且仅有 \(S\) 中的狗 ...
- UOJ 【UR #5】怎样跑得更快
[UOJ#62]怎样跑得更快 题面 这个题让人有高斯消元的冲动,但肯定是不行的. 这个题算是莫比乌斯反演的一个非常巧妙的应用(不看题解不会做). 套路1: 因为\(b(i)\)能表达成一系列\(x(i ...
- UOJ #22 UR #1 外星人
LINK:#22. UR #1 外星人 给出n个正整数数 一个初值x x要逐个对这些数字取模 问怎样排列使得最终结果最大 使结果最大的方案数又多少种? n<=1000,x<=5000. 考 ...
- UOJ.52.[UR #4]元旦激光炮(交互 思路)
题目链接 \(Description\) 交互库中有三个排好序的,长度分别为\(n_a,n_b,n_c\)的数组\(a,b,c\).你需要求出所有元素中第\(k\)小的数.你可以调用至多\(100\) ...
- UOJ【UR #12】实验室外的攻防战
题意: 给出一个排列$A$,问是否能够经过以下若干次变换变为排列$B$ 变换:若${A_i> A_i+1}$,可以${swap(A_i,A_i+1)}$ 考虑一个数字从A排列到B排列连出来的路径 ...
- 【UOJ#33】【UR#2】树上GCD 有根树点分治 + 容斥原理 + 分块
#33. [UR #2]树上GCD 有一棵$n$个结点的有根树$T$.结点编号为$1…n$,其中根结点为$1$. 树上每条边的长度为$1$.我们用$d(x,y)$表示结点$x,y$在树上的距离,$LC ...
- uoj #118. 【UR #8】赴京赶考 水题
#118. [UR #8]赴京赶考 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/118 Description ...
- uoj #31. 【UR #2】猪猪侠再战括号序列 贪心
#31. [UR #2]猪猪侠再战括号序列 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/31 Descript ...
随机推荐
- DButils实现增删查改
获取数据库连接 static Connection con=JdbcUtils.MyUtils();//这个连接类静态获取要自己定义 插入 public static void insert() th ...
- DRF跨域,简单请求和复杂请求
跨域就是跨域名,跨端口 - 为什么会有跨域? 浏览器有同源限制策略 - 绕过浏览器同源策略就可以跨域 - 方式一: jsonp(利用浏览器特性) 在html动态创建script标签 同源策略会阻止a ...
- FreeRTOS任务函数
FreeRTOS的任务函数原型如下:void ATaskFunction(void *pvParameters); void ATaskFunction(*pvParameters){;; //函数可 ...
- 【Codeforces 1137B】Camp Schedule
Codeforces 1137 B 题意:给两个串\(S\).\(T\),问将\(S\)中字符任意调换后出现\(T\)次数最多的方案. 思路:我们首先考虑怎么样放\(T\)才是最优的.我们直观上考虑前 ...
- Tensorflow[源码安装时bazel行为解析]
0. 引言 通过源码方式安装,并进行一定程度的解读,有助于理解tensorflow源码,本文主要基于tensorflow v1.8源码,并借鉴于如何阅读TensorFlow源码. 首先,自然是需要去b ...
- CF1070L Odd Federalization 高斯消元
传送门 \(r = 1\)直接判断所有点度数是否为偶数 考虑\(r = 2\)的情况.设\(x_i=0/1\)表示\(i\)点所在的集合,那么若\(2 \mid du_u\),则\(\bigoplus ...
- ES6-课程介绍
ES6 可以提高开发效率,把ES3比做斧头,ES5比做锯子,那么ES6就是电锯. ES6新特性 默认参数.字符串模板.结构赋值.箭头函数.set\mat .异步操作.类和对象 .模块化
- (转)Putty server refused our key的三种原因和解决方法
原文 上一篇博文介绍了使用Putty免密码登录,我后面试了另一台虚拟机,结果putty显示错误server refused our key(在linux下则表现为仍需要输入密码),搜索了下,很多人都遇 ...
- Ubuntu 16.04 下部署Node.js+MySQL微信小程序商城
转载于这篇文章 关于pm2看这篇文章 最近在研究小程序,申请了域名之后,再一次来配置环境,根据作者的步骤基本上完成了网站的架构,但由于环境路径等不同,配置上会有所不同,因此记录下来. 1.更新系统和安 ...
- H+ 后台主题UI框架
十年河东,十年河西,莫欺少年穷 学无止境,精益求精 今天得到了一个非常完美的后端管理系统框架:H+ 后台主题UI框架 H+ 后台主题UI框架 H+是一个完全响应式,基于Bootstrap3.3.6最新 ...