「UR#6」懒癌

妈妈我居然看了六个小时题解,快救救乌干达的可怜儿童吧。

接下来开始膜官方题解:

​ 其实就算有上面两个结论也不是很好想到任意复杂度的做法,关键在于要想到一个人是怎么推断自己的狗是不是懒狗的,这个过程显然不是 \(\mathcal O(1)\) 级别的。膜一下官方题解可以知道,一个人判断自己的狗是不是懒狗,会假设自己的狗不是懒狗,然后枚举一下其看不到的狗究竟是不是懒狗的各种情况,得到一个其想象的状态 \(S'\) ,如果所有 \(S'\) 的开枪时间都小于当前时刻,那么说明他的狗一定是懒狗,他就会开枪。

​ 那么可以得到一个指数级别的做法,记 \(f[S]\) 表示 \(S\) 集合的开枪时间,枚举 \(S\) 中的每一条懒狗,在其主人所有想象的状态 \(S'\) 中取一个 \(\max(f[S'])+1\) ,表示这个人开枪的时间,最后在所有人的开枪时间里取一个 \(\min\) 。然后会发现转移实际上是有环的,有环实际上是有两个状态的时间都是对方开枪的时间 \(+1\) ,不难发现如果枚举其中一条懒狗的转移是有环的,那么这个状态中所有懒狗的转移都是会到达一个环的,因为出现环的情况的本质是有两个人互相看不到对方且其中至少一个人的狗是懒狗。

​ 然后考虑把这张图的补图建出来,考虑转移有环的条件就是一个点能到达一个环,把这些点全部日掉就得到了一个 \(\text{DAG}\) ,我们把懒狗看做黑点,正常的狗看做白点,一个黑点集合的答案可以看做这样一个东西:

​ 每次选取其中的一个黑点染白,然后将其所有后继节点染白,直到所有节点都变成白色,答案就是过程中被染黑的节点数量。为什么呢?考虑将一个节点从黑色被染成白色的时候看做选取了这个人来想象,这个时候它就假装自己不是懒狗了,所以染白,然后选取一些后继节点(看不见的节点)来钦定它们的黑白,这个时候加上一点贡献对应着原转移的 \(+1​\) 。因为要取 \(\max​\) 所以每次一定选的是所有的后继节点。而每个被染黑的节点只计算一次贡献是因为每次选择当前拓扑序最小的节点可以保证每个点只被染黑一次,这是一个永远可以取到的下界,对应着取 \(\min​\) 操作。

​ 那么一个节点对开枪时间有贡献当且仅当选取了一个黑点能到达它,对杀狗数量有贡献当且仅当所有选取的黑点除了它以外没节点能到达它,统计一下能到达每个点的点的数量即可,bitset搞搞,\(\mathcal O(\frac{n^3}{64})\) 。

​ 题目中给了个条件,如果一个人听到枪声就不会开枪杀狗,过了以后膜了下jls发现这个条件是多余的。假设第 \(i\) 时刻有人开了一枪,在第 \(x\) 人在之后还会再开枪,那么他会推断出一个最晚开枪时间 \(j\),如果 \(j\) 之前没人开枪他就会在第 \(j\) 时刻开枪。如果 \(j <i\) ,那么这个人会先于 \(i\) 开枪,否则因为 \(i<j\) ,在 \(j\) 之前有人开枪,所以 \(x\) 不会开枪。

code

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef unsigned long long ull;
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 3005, mod = 998244353;
queue<int> q;
bitset<N> f[N], B[N];
char s[N];
int a[N][N], deg[N], inc[N], n, m, ans1, ans2;
inline void up(int &x, int y){
x = x + y >= mod ? x + y - mod : x + y;
}
inline int Pow(int a, int b){
int ans = 1;
for(; b; b >>= 1, a = 1ll * a * a % mod)
if(b & 1) ans = 1ll * ans * a % mod;
return ans;
}
inline void gao(int x){
up(ans1, (Pow(2, m) - Pow(2, m - x - 1) + mod) % mod);
up(ans2, (Pow(2, m - 1) - 1ll * (Pow(2, x) - 1) * Pow(2, m - x - 1) % mod + mod) % mod);
}
int main(){
read(n);
for(int i = 1; i <= n; i++){
scanf("%s", s + 1);
for(int j = 1; j <= n; j++)
a[i][j] = (s[j] == '0');
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++){
f[i][j] = a[i][j];
if(i == j) f[i][j] = 1;
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(f[i][j]) f[i] |= f[j];
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++)
if(f[i][j] && f[j][i]) inc[i] = inc[j] = 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(f[i][j] && inc[j]) inc[i] = 1;
for(int i = 1; i <= n; i++) if(!inc[i]) m++;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(!inc[i] && !inc[j] && a[i][j] && i != j) deg[j]++;
for(int i = 1; i <= n; i++)
if(!inc[i] && !deg[i]) q.push(i);
for(; !q.empty(); q.pop()){
int u = q.front();
gao(B[u].count());
B[u][u] = 1;
for(int i = 1; i <= n; i++)
if(a[u][i] && !inc[i]){
B[i] |= B[u];
if(!--deg[i]) q.push(i);
}
}
cout << ans1 << " " << ans2 << endl;
return 0;
}

「UR#6」懒癌的更多相关文章

  1. 「UR#5」怎样跑得更快

    「UR#5」怎样跑得更快 膜这个您就会了 下面是复读机mangoyang 我们要求 \[ \sum_{j=1}^n \gcd(i,j)^{c-d} j^d x_j=\frac{b_i}{i^d} \] ...

  2. 「UR#5」怎样更有力气

    「UR#5」怎样更有力气 解题思路 考虑没有限制的情况,一定是把操作离线下来,按照边权从小到达做.可以发现,如果没有限制,完全图是多余的,直接拿树边进行合并就可以了.我们要做这么一件事情,把每个点属于 ...

  3. Solution -「UR #21」「UOJ #632」挑战最大团

    \(\mathcal{Description}\)   Link.   对于简单无向图 \(G=(V,E)\),定义它是"优美"的,当且仅当 \[\forall\{a,b,c,d\ ...

  4. Solution -「UR #2」「UOJ #32」跳蚤公路

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的带权有向图,每条边还有属性 \(s\in\{-1,0,1\}\).对于每个 \(u ...

  5. loj #2023. 「AHOI / HNOI2017」抛硬币

    #2023. 「AHOI / HNOI2017」抛硬币   题目描述 小 A 和小 B 是一对好朋友,他们经常一起愉快的玩耍.最近小 B 沉迷于**师手游,天天刷本,根本无心搞学习.但是已经入坑了几个 ...

  6. 前端构建工具之gulp(一)「图片压缩」

    前端构建工具之gulp(一)「图片压缩」 已经很久没有写过博客了,现下终于事情少了,开始写博吧 今天网站要做一些优化:图片压缩,资源合并等 以前一直使用百度的FIS工具,但是FIS还没有提供图片压缩的 ...

  7. fir.im Weekly - 如何打造 Github 「爆款」开源项目

    最近 Android 转用 Swift 的传闻甚嚣尘上,Swift 的 Github 主页上已经有了一次 merge>>「Port to Android」,让我们对 Swift 的想象又多 ...

  8. 更新日志 - fir.im「高级统计」功能上线

    距离 2016 年到来只剩 10 个日夜,fir.im 也准备了一些新鲜的东西,比如「高级统计」功能和「跳转应用商店」功能,帮助你更好地管理.优化应用,欢迎大家试用反馈:) 新增高级统计功能 这次更新 ...

  9. Notepad++ 开启「切分窗口」同时检视、比对两份文件

    Notepad++ 是个相当好用的免费纯文本编辑器,除了内建的功能相当多之外,也支持外挂模块的方式扩充各方面的应用.以前我都用 UltraEdit 跟 Emeditor,后来都改用免费的 Notepa ...

随机推荐

  1. dajngo控制台添加数据报错Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured.

    报错: django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but set ...

  2. 【AtCoder】 ARC 100

    link C-Linear Approximation 给出\(N\)个数\(A_1,A_2,...,A_N\) ,求一个数\(d\),最小化\(\sum_{i=1}^N|A_i-(d+i)|\) 把 ...

  3. Writeup:第五届上海市大学生网络安全大赛-Web

    目录 Writeup:第五届上海市大学生网络安全大赛-Web 一.Decade 无参数函数RCE(./..) 二.Easysql 三.Babyt5 二次编码绕过strpos Description: ...

  4. hdu1276士兵队列训练问题[简单STL list]

    目录 题目地址 题干 代码和解释 题目地址 hdu1276 题干 代码和解释 本题使用了STL中的list,STL的list是双向链表.它的内存空间不必连续,通过指针来进行数据的访问,高效率地在任意地 ...

  5. 利用Windows内置工具winsat测试硬盘速度(SSD&机械盘对比)

    利用Windows内置工具winsat测试硬盘速度(SSD&机械盘对比) 以下是红色内容是在命令行运行: C:\Users\Administrator>winsat diskWindow ...

  6. vs code搭建python和tensorflow环境

    anaconda 安装tensorflow-gpu环境见https://www.cnblogs.com/wintersoft/p/11620267.html vscode中设置python虚拟环境Ct ...

  7. java和vue2.0

    1 java中的el表达式${对象.属性}和vue中的双向数据绑定{{mode.xx}}感觉有点类似 2 java中  request.setAttribute("hots", l ...

  8. SpringMVC(十五):Dispatcher的重要组件之一MultipartResolver(StandardServletMultipartResolver和CommonsMultipartResolver)的用法

    MultipartResolver组件 从Spring官网上可以看到MultipartResolver接口的定义信息: public interface MultipartResolver A str ...

  9. Ubuntu 16.04.4 LTS下安装OpenSSL

    1.下载openssl,本次下载的版本是openssl-1.1.0l.tar.gz : 地址  https://www.openssl.org/source/openssl-1.1.0l.tar.gz ...

  10. MLflow系列2:MLflow追踪

    英文链接:https://mlflow.org/docs/latest/tracking.html 本文链接:https://www.cnblogs.com/CheeseZH/p/11945089.h ...