Problem

Description

你绞尽脑汁也没有解开智商锁给的迷题,只见哐地一下门就开了:“您与锁的主人智商一致。”

于是你们窃取了大量内部资料,最后端掉了 \(IIIS\)。

但是,虽然 \(IIIS\) 被摧毁了,当地居民仍有大量在星期八休息的,而且看不惯在星期日休息的人,在星期日休息的人同样看不惯在星期八休息的人,于是整个社会秩序被打乱得一塌糊涂。

当地共有 \(2^n - 1\) 个村庄,每个村庄住着 \(n\) 户人家,门牌号分别为 \(1, 2, \dots, n\),每户人家家里养着一条狗。恰逢无药可治的懒癌流行,人人自危。每个村庄都有至少一只狗得了懒癌。一个村庄中,门牌号为 \(i\) 的人家的狗要么得懒癌,要么不得懒癌,一共 \(2^n\) 种情况,再去掉都没得懒癌的情况,一共 \(2^n - 1\) 种。这每种情况都会发生在恰好一个村庄中。

这天来了个善良的人来到每个村庄中,告诉所有人一个爆炸性的新闻:“你们村里至少有一只狗得了懒癌!”

每个村庄中每户人家都不知道自己的狗到底是懒癌还是可爱,但是他能一眼看出某些人家的狗有没有得懒癌。由于这个社会里人与人之间的信任已经崩塌,一个人即使看出别人的狗是否得懒癌也不愿告诉他。

可以用一个 \(n\) 个结点的有向图来描述可见性,\(v\) 到 \(u\) 有一条有向边表示门牌号为 \(v\) 的人家能看出门牌号为 \(u\) 的家里的狗是否得了懒癌,没边则表示看不出。每个人都知道这张有向图。

于是一个残酷的逻辑链条开始启动。对于每个村庄:

第一天,早上每户人家的主人会出门看看别人家的狗,如果一个人能推断出自己家的狗得了懒癌,下午6点整,他就会掏出手枪一枪把自己家的狗毙了。

如果有多个人都在同一天推断出了,那么他们会在下午6点整同时开枪。

每个人都听得到这个村庄里的枪声。如果没有听到枪声,这个村里的人第二天会继续早上出门看狗,推断出自己家狗得了懒癌下午就杀狗。如果还没有听到枪声,第三天也会如此,依次类推。(所以如果一个人听到了枪声那么就不会再开枪杀狗)

作为一个想帮助当地居民调节矛盾的你想要向当地居民展示灾难性的后果,请计算出对于所有前 \(233^n\) 天内有过枪声的村庄:

开枪时间之和。如一个村庄在第 \(k\) 天下午响起枪声,则开枪时间为 \(k\)。(多个人同时开枪只算一次)

死亡的狗的总数。

你只用输出对 \(998244353\)(\(7 \times 17 \times 2^{23} + 1\),一个质数)取模后的结果。

输入格式

第一行一个整数 \(n\),含义如前所述。

接下来 \(n\) 行每行 \(n\) 个字符,表示可见性。这 \(n\) 行中的第 \(v\) 行第 \(u\) 个字符为 “1” 表示 \(v\) 能看出 \(u\) 家的狗是否得懒癌,如果字符为 “0” 表示看不出。保证只会出现 “0” 和 “1” 这两种字符,且对于任意一个满足 \(1 \leq v \leq n\) 的 \(v\),第 \(v\) 行第 \(v\) 列为 “0”。

Input Format

第一行一个整数 \(n\),含义如前所述。

接下来 \(n\) 行每行 \(n\) 个字符,表示可见性。这 \(n\) 行中的第 \(v\) 行第 \(u\) 个字符为 “1” 表示 \(v\) 能看出 \(u\) 家的狗是否得懒癌,如果字符为 “0” 表示看不出。保证只会出现 “0” 和 “1” 这两种字符,且对于任意一个满足 \(1 \leq v \leq n\) 的 \(v\),第 \(v\) 行第 \(v\) 列为 “0”。

Output Format

一行输出两个整数分别表示开枪时间和、死亡的狗的总数。

Sample

Input 1

2
01
00

Output 1

5 3

Input 2

2
01
10

Output 2

4 4

Explanation

Explanation for Input 1

门牌号为 1 的人能看见门牌号为 2 的人家里的狗是不是病狗。

共有三个村庄。

1 病了,2 没病。第一天 1 发现 2 没得病,又知道他们中肯定有一个病了,所以第一天下午开枪杀了狗。开枪时间为 \(1\),死了 \(1\) 只狗。

1 没病,2 病了。第一天 1 发现 2 得了病,于是第一天两个人什么也没干。第二天 2 发现前一天 1 没有开枪,所以下午开枪杀了狗。开枪时间为 \(2\),死了 \(1\) 只狗。

1 病了,2 病了。2 还是第二天开枪杀了狗,1 始终没有开枪。开枪时间为 \(2\),死了 \(1\) 只狗。

所以 \(1 + 2 + 2 = 5\),\(1 + 1 + 1 = 3\)。

Range

对于 \(20\%\), \(n \leq 8\)

对于 \(20\%\), \(n \leq 20\)

对于 \(20\%\), \(n \leq 100\)

对于 \(10\%\), \(n \leq 3000\) 每户人家都能看出其他每户人家的狗有没有得懒癌

对于 \(30\%\), \(n \leq 3000\)

Algorithm

强联通分量

Mentality

好神的题 \(stO\) 。

对于一个主人,我们想一下,他在知道这张关系的有向图的情况下,他会怎么考虑?

最暴力的方法:当然是 \(2\) 的幂次枚举所有 他看不到的狗 的得病情况,然后在所有情况里,取可能的开枪时间的最大值。如果到了这个时间还没有人开枪,那就说明自己的狗狗有问题,当天就会把狗 \(bong\) 了。

不过这个太暴力了。

换一种想法,对于一个狗主人,他的思维模式应该是这样子:先假设自己的狗没有生病,然后对于每个看不到的狗,分别假设它们生了病,然后推断看不到的狗的主人又会怎样推断,最后得到最大天数,而其他狗主人也会向这样递归推理。

则我们考虑对于看不到的关系建有向图。

有病的狗为黑点没病的狗为白点,那么每个主人思考的本质就是将自己的点染白,然后将所有后继结点染黑。

这样一来,天数就只与这种染色关系的传递有关。

随后,我们发现,如果这张图的某个点,它能够传到一个强联通分量里,那就永远不会开枪了,因为这样的推理链会陷入一个无限的死循环。

则对于所有能到达强联通分量的点,我们将它们删去,因为它们若为黑点,则永远不会贡献答案。那么最后就会剩下一个漂亮的 \(DAG\) 。

考虑这种情况下的开枪时间。

对于一个黑点 \(x\),将它能直接到达的所有结点称为后继集合,由于能看到后继集合以外的所有点,那么除了后继集合,它都不需要推测其他结点长什么样子。如果它的后继集合中也存在一个黑点 \(y\),那么由于 \(y\) 能够看到 \(x\) ,根据这个题目最原始的形式(也就是没有有向图限制),则 \(y\) 的一切推论必须建立在 \(x\) 不开枪 的基础上。

换句话说,\(y\) 的开枪时间只可能比 \(x\) 晚。

那么,要计算 \(x\) 的开枪时间,无需管后继集合中的黑点。换句话说,我们只需要计算在 \(x\) 的后继集合中没有黑点,同时 \(x\) 为黑点的最大开枪时间即可。

这样我们需要处理的黑点集合必定满足两两之间互不可达,并且能够看见除了自己的后继集合以外的所有点。那对于任意一个点,它一定能推断出其他点当自己为白点情况下的最小开枪时间,如果到时间还没有开枪,那么当天晚上就会把自己的狗杀掉。

不难得出,这些黑点推断出自己是黑点的时间相同。

考虑使用归纳法。

先看只有一个黑点的情况。

对于当前点 \(x\) ,设 \(x\) 为黑点,图中其他全为白点。

对于出度为零的末梢结点,它能看到所有结点且能看到后继集合,由于一定有黑点,开枪天数为 \(1\)。

对于后继结点出度都为零的结点,它会先假设后继结点都为 \(1\) ,由于后继结点互相可见,那么最大开枪时间为结点个数。

则此结点开枪时间为后继结点个数 \(+1\) 。

依次推论归纳下去,对于每个点,后继集合中没有黑点且自己为黑点的开枪时间为后继集合中的结点个数 \(+1\) 。

换句话说,它的答案就是自己能到达的点数。

考虑存在 \(2\) 个黑点的情况。对于其中任意一个黑点而言,它能知道如果自己的后继集合里都为白点,另一个黑点的开枪时间。如果到时间还没有开枪,则说明自己的后继集合中有黑点。于是还要花上自己的时间来推出自己为黑点。

这样的话,答案就是两个黑点能到达的点数之和。

推论归纳下去,对于一个互不可达的黑点集合,答案为集合中的点能够到达的点数之和。

所以我们第一问要求的就是:在所有情况中,所有黑点的 后继集合的并 的数量和。

考虑转换成每个点的贡献。设每个点能够被 \(k\) 个结点到达,则它的贡献为 \((2^k-1)*2^{n-k}\) 。

对于第二问,就是问所有情况中,不能被任何黑点到达的黑点的数量之和。

这种情况下,每个黑点的贡献为 \(2^{n-k}\) 。

对于求 \(DAG\) 中每个点能被多少个点到达,直接 \(bitset\) 优化,得到 \(O(\frac{nm}{32})\) 复杂度。

完毕。

Code

#include <bits/stdc++.h>
using namespace std;
long long read() {
long long x = 0, w = 1;
char ch = getchar();
while (!isdigit(ch)) w = ch == '-' ? -1 : 1, ch = getchar();
while (isdigit(ch)) {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar();
}
return x * w;
}
const int Max_n = 3005, mod = 998244353;
int n, Res, ans1, ans2;
int cntt, dfn[Max_n], low[Max_n], bel[Max_n], num[Max_n];
int cntp, in[Max_n], top[Max_n];
char P[Max_n][Max_n];
bool bk[Max_n], ins[Max_n];
vector<int> r[Max_n];
bitset<Max_n> s[Max_n];
stack<int> stk;
queue<int> q;
void dfs(int x) {
dfn[x] = low[x] = ++cntt;
stk.push(x), ins[x] = 1;
for (auto to : r[x]) {
if (!dfn[to])
dfs(to), low[x] = min(low[x], low[to]);
else if (ins[to])
low[x] = min(low[x], dfn[to]);
}
if (dfn[x] == low[x]) {
bel[x] = x;
while (stk.top() != x) bel[stk.top()] = x, ins[stk.top()] = 0, stk.pop();
ins[stk.top()] = 0, stk.pop();
}
}
void del(int x) {
for (int i = 1; i <= n; i++)
if (x != i && bk[i] && P[i][x] == '0')
bk[i] = 0, del(i);
}
int ksm(int a, int b) {
int res = 1;
for (; b; b >>= 1, a = 1ll * a * a % mod)
if (b & 1) res = 1ll * res * a % mod;
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("76.in", "r", stdin);
freopen("76.out", "w", stdout);
#endif
Res = n = read();
for (int i = 1; i <= n; i++) {
scanf("%s", P[i] + 1), s[i].set(i), bk[i] = 1;
for (int j = 1; j <= n; j++)
if (P[i][j] == '0' && i != j)
r[i].push_back(j);
}
for (int i = 1; i <= n; i++)
if (!dfn[i]) dfs(i);
for (int i = 1; i <= n; i++) num[bel[i]]++;
for (int i = 1; i <= n; i++)
if (num[bel[i]] > 1) bk[i] = 0;
for (int i = 1; i <= n; i++)
if (!bk[i]) del(i);
for (int i = 1; i <= n; i++) Res -= !bk[i];
for (int i = 1; i <= n; i++)
if (bk[i])
for (auto to : r[i]) in[to]++;
for (int i = 1; i <= n; i++)
if (!in[i] && bk[i]) q.push(i);
while (!q.empty()) {
top[++cntp] = q.front();
for (auto to : r[q.front()])
if (bk[to] && !(--in[to])) q.push(to);
q.pop();
}
for (int i = 1; i <= cntp; i++) {
int x = top[i];
for (auto to : r[x])
if (bk[to]) s[to] |= s[x];
}
for (int i = 1; i <= cntp; i++) {
int x = top[i];
int tot = s[x].count();
ans1 = (ans1 + 1ll * (ksm(2, tot) - 1) * ksm(2, Res - tot) % mod) % mod;
ans2 = (ans2 + ksm(2, Res - tot)) % mod;
}
cout << ans1 << " " << ans2 << endl;
}

【UR #6】懒癌的更多相关文章

  1. 【UOJ#76】【UR #6】懒癌(动态规划)

    [UOJ#76][UR #6]懒癌(动态规划) 题面 UOJ 题解 神....神仙题. 先考虑如果是完全图怎么做... 因为是完全图,所以是对称的,所以我们只考虑一个有懒癌的人的心路历程. 如果只有一 ...

  2. 「UR#6」懒癌

    「UR#6」懒癌 妈妈我居然看了六个小时题解,快救救乌干达的可怜儿童吧. 接下来开始膜官方题解: ​ 其实就算有上面两个结论也不是很好想到任意复杂度的做法,关键在于要想到一个人是怎么推断自己的狗是不是 ...

  3. UOJ #76 -【UR #6】懒癌(思维题)

    UOJ 题面传送门 神仙题. orz czx,czxyyds 首先没有懒癌的狗肯定不会被枪毙,证明显然. 接下来考虑怎样计算一种局面的答案,假设 \(dp_S\) 表示对于有且仅有 \(S\) 中的狗 ...

  4. UOJ #76 【UR #6】懒癌

    确实是一道很不错的题啊. 题目链接 题意 感觉也没什么特别简洁的版本,大家直接看题面吧. 题解 我第一次看到这个类似问题的背景是疯狗,因此下面的题解不自觉的代入了...大家明白意思就好. 我们考虑对于 ...

  5. 【UR #7】水题走四方

    题目描述 今天是世界水日,著名的水题资源专家蝈蝈大臣发起了水题走四方活动,向全世界发放成千上万的水题. 蝈蝈大臣是家里蹲大学的教授,当然不愿意出门发水题啦!所以他委托他的助手欧姆来发. 助手欧姆最近做 ...

  6. ur c题练习

    ur的c果然sxbk啊 ur5:“三个莫比乌斯反演掷地有声"——摘自v(c)f(z)k(y)语录,无删改 ur2:有根树分治裸题,复杂度玄学$O(n\sqrt{n})$. 首先,转化为统计k ...

  7. db2 with ur

    这几天查询DB2数据库,老遇到select * from XXX with ur, 好奇ur是什么作用,现在记录一下. DB2中,共有四种隔离级:RS,RR,CS,UR,DB2提供了这4种不同的保护级 ...

  8. 【UOJ#33】【UR#2】树上GCD 有根树点分治 + 容斥原理 + 分块

    #33. [UR #2]树上GCD 有一棵$n$个结点的有根树$T$.结点编号为$1…n$,其中根结点为$1$. 树上每条边的长度为$1$.我们用$d(x,y)$表示结点$x,y$在树上的距离,$LC ...

  9. uoj #118. 【UR #8】赴京赶考 水题

    #118. [UR #8]赴京赶考 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/118 Description ...

随机推荐

  1. 在文件夹下所有文件中查找字符串(linux/windows)

    在linux下可以用 grep "String" filename.txt#字符串 文件名grep -r "String" /home/#递归查找目录下所有文件 ...

  2. 机器学习笔记(十)---- KNN(K Nearst Neighbor)

    KNN是一种常见的监督学习算法,工作机制很好理解:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个"邻居"的信息来进行预测.总结一句话就是&quo ...

  3. 一条数据的HBase之旅,简明HBase入门教程4:集群角色

    [摘要] 本文主要介绍HBase与HDFS的关系,一些关键进程角色,以及在部署上的建议 HBase与HDFS 我们都知道HBase的数据是存储于HDFS里面的,相信大家也都有这么的认知: HBase是 ...

  4. 转:Spring配置文件<context:property-placeholder>标签使用漫谈

    <context:property-placeholder>标签提供了一种优雅的外在化参数配置的方式,不过该标签在Spring配置文件中只能存在一份!!! 众所周知,Spring容器是采用 ...

  5. RS485与RS232

    以下内容为结合视频,加上自述对其理解. 信息在传输线上通过电压信息进行传输,一个字节的数据有8位. 当传输一个字节的信息时,通信方式有串行通信与并行通信,在这两种通信方式之中,RS485是并行通信,R ...

  6. CentOS 6 编译 TensorFlow for Java 以及 Maven Pom

    我们的系统环境 CentOS 6.5, JDK 1.8 更新yum源 $ yum update 安装 Python 2.7 $ yum install python27 python27-numpy ...

  7. Spring Cloud第五篇 | 服务熔断Hystrix

    ​ 本文是Spring Cloud专栏的第五篇文章,了解前四篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring Clo ...

  8. HDU5343 MZL's Circle Zhou(SAM+记忆化搜索)

    Problem Description MZL's Circle Zhou is good at solving some counting problems. One day, he comes u ...

  9. Spring Security OAuth2 Demo —— 密码模式(Password)

    前情回顾 前几节分享了OAuth2的流程与授权码模式和隐式授权模式两种的Demo,我们了解到授权码模式是OAuth2四种模式流程最复杂模式,复杂程度由大至小:授权码模式 > 隐式授权模式 > ...

  10. Python绘制KS曲线

    更多大数据分析.建模等内容请关注公众号<bigdatamodeling> python实现KS曲线,相关使用方法请参考上篇博客-R语言实现KS曲线 代码如下: ############## ...