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 ...
随机推荐
- PAT A1107 Social Clusters (30 分)——并查集
When register on a social network, you are always asked to specify your hobbies in order to find som ...
- 【Codeforces 1114F】Please, another Queries on Array?
Codeforces 1114 F 题意:给你一个序列\(a_{1\dots n}\),以及\(q\)次查询,每次查询有两种格式: TOTIENT \(l\) \(r\):求出\(\phi(\Pi_{ ...
- java static 在java 中的使用。
static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何 ...
- Android学习之基础知识九 — 数据存储(持久化技术)之SQLite数据库存储
前面一讲介绍了数据持久化技术的前两种:文件存储.SharedPreferences存储.下面介绍第三种技术:SQLite数据库存储 一.SQLite数据库存储 SQLite数据库是一款轻量级的关系型数 ...
- 车轮升级PHP7踩过的一些坑
社区php7升级记录 社区服务器已经全部完成升级,这里记录一下社区升级php7所遇到的问题,可以分为四个类型 扩展支持的变化,导致需要修改配置甚至调整替换操作的类库 php7语法检查比之前变得严格,部 ...
- React-state props与render()的关系
state或者props发生改变,render()j就会执行一次. 父组件的render()被重新执行时,它的子组件的render()都会重新执行.
- ionic访问odoo 11接口
在架设完毕odoo 11的网站之后,第一次面临手机app该如何访问后台网站的问题,是不是模式类似asp.net mvc 那样的模式,或者还存在其他的访问方法,带着这个疑问与困惑,开始的我的研究学习之路 ...
- 大话设计模式:代理模式 C#
学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现在,学习代表你的将来 所谓代理模式就是你去委托一个人帮你干一件事!例如:你委托我帮你谈恋爱,你委托我帮你陪你媳妇儿逛 ...
- 快速零配置迁移 API 适配 iOS 对 IPv6 以及 HTTPS 的要求
本文快速分享一下快速零配置迁移 API 适配 iOS 对 IPv6 以及 HTTPS 的要求的方法,供大家参考. 原文发表于我的技术博客 零配置方案 最新的苹果审核政策对 API 的 IPv6 以及 ...
- CentOS 网卡自动启动、配置等ifcfg-eth0教程
装完centos后发现网卡没有自动启动, vi /etc/sysconfig/network-scripts/ifcfg-eth0 将ONBOOT=no 改为yes即可 原文链接: http://yp ...