JZOJ 5062. 【GDOI2017第二轮模拟day1】航海舰队
\(\text{Solution}\)
这还是 [Lydsy2017省队十连测] 的题
不得不说 \(FFT\) 在字符串匹配中的妙啊!
前面做了道一维的题,现在这是二维的
从题目入手,不考虑可不可达
如果舰队从天而降,考虑其可以落到以那些点为左上角的点
先将地图压成一维,一行接着一行,礁石处为 \(1\) 其余为 \(0\)
抽出包含舰队的最小矩形,按照原来地图行长,从矩阵开头到结尾压成一维,舰队处为 \(1\),其余为 \(0\)
构造匹配函数 \(F_i\) 表示大矩形以 \(i\) 为左上角能否匹配,\(F_i =\sum_j A_{i+j}\cdot B_j\)
则 \(F_i = 0\) 是可行,将 \(A\) 翻转,\(F_i=\sum_j A_{n\cdot m-1-i-j}\cdot B_j\)
这是一个多项式卷积形式,\(NTT\) 即可
于是我们得到了若干个可放入舰队的左上角
我们还要知道那些左上角可达,从小矩阵左上角开始 \(BFS\) 即可
然而我们仍需要那些空地可以被舰队掠过
考虑将可达左上角即为 \(1\),其余为 \(0\),\(B\) 中舰队为 \(1\)
那么 \(i\) 位置可达,需要存在一个可达左上角 \(i-j\)
考虑构造函数 \(F_i = \sum_j A_{i-j} \cdot B_{j}\)
当 \(F_i > 0\) 则该位置可达
发现仍是多项式卷积形式,继续 \(NTT\) 即可
\(\text{Code}\)
#include <cstdio>
#include <iostream>
#define RE register
#define IN inline
using namespace std;
typedef long long LL;
const int N = 705, P = 998244353, g = 3;
char str[N][N];
int n, m, vis[N][N], x0 = N, y0 = N, x1 = 0, y1 = 0, rev[N * N * 2];
int fx[4][2] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}};
LL a[N * N * 2], b[N * N * 2];
struct Point{int x, y;}Q[N * N];
IN int Get(int x, int y){return (x - 1) * m + y - 1;}
IN int get(int x, int y){return (x - x0) * m + y - y0;}
IN int fpow(LL x, int y){LL s = 1; for(; y; y >>= 1, x = x * x % P) if (y & 1) s = s * x % P; return s;}
IN void NTT(LL *a, int n, int inv)
{
if (n == 1) return;
for(RE int i = 0; i < n; i++) if (i < rev[i]) swap(a[i], a[rev[i]]);
for(RE int mid = 1; mid < n; mid <<= 1)
{
int I = fpow(g, (P - 1) / (mid << 1));
if (inv == -1) I = fpow(I, P - 2);
for(RE int i = 0; i < n; i += (mid << 1))
{
LL W = 1;
for(RE int j = 0, x, y; j < mid; j++, W = W * I % P)
x = a[i + j], y = W * a[i + j + mid] % P,
a[i + j] = (x + y) % P, a[i + j + mid] = (x - y + P) % P;
}
}
}
void BFS()
{
int head = 0, tail = 1; Q[1] = Point{x0, y0}, vis[x0][y0] = 0;
while (head < tail)
{
Point z = Q[++head]; a[Get(z.x, z.y)] = 1;
for(RE int k = 0; k < 4; k++)
{
int x = z.x + fx[k][0], y = z.y + fx[k][1];
if (x > 0 && x <= n && y > 0 && y <= m && vis[x][y]) vis[x][y] = 0, Q[++tail] = Point{x, y};
}
}
}
int main()
{
freopen("sailing.in", "r", stdin), freopen("sailing.out", "w", stdout);
scanf("%d%d", &n, &m);
for(RE int i = 1; i <= n; i++) scanf("%s", str[i] + 1);
for(RE int i = 1; i <= n; i++)
for(RE int j = 1; j <= m; j++)
if (str[i][j] == 'o') x0 = min(x0, i), y0 = min(y0, j), x1 = max(x1, i), y1 = max(y1, j);
else if (str[i][j] == '#') a[n * m - 1 - Get(i, j)] = 1;
for(RE int i = 1; i <= n; i++)
for(RE int j = 1; j <= m; j++) if (str[i][j] == 'o') b[get(i, j)] = 1;
int lim = 1; while (lim < n * m) lim <<= 1; int inv = fpow(lim, P - 2);
int bit = 0; while ((1 << bit) < lim) bit++;
for(RE int i = 0; i < lim; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
NTT(a, lim, 1), NTT(b, lim, 1);
for(RE int i = 0; i < lim; i++) a[i] = a[i] * b[i] % P;
NTT(a, lim, -1); for(RE int i = 0; i < lim; i++) a[i] = a[i] * inv % P;
for(RE int i = 1; i <= n + x0 - x1; i++)
for(RE int j = 1; j <= m + y0 - y1; j++)
if (!a[n * m - 1 - Get(i, j)]) vis[i][j] = 1;
for(RE int i = 0; i < lim; i++) a[i] = 0;
BFS(), NTT(a, lim, 1);
for(RE int i = 0; i < lim; i++) a[i] = a[i] * b[i] % P;
NTT(a, lim, -1); for(RE int i = 0; i < lim; i++) a[i] = a[i] * inv % P;
int ans = 0;
for(RE int i = 0; i < n * m; i++) if (a[i] > 0) ans++;
printf("%d\n", ans);
}
JZOJ 5062. 【GDOI2017第二轮模拟day1】航海舰队的更多相关文章
- GDOI2017第二轮模拟day1 总结
平民比赛 这场比赛的暴力分非常友好. 但是我并没有拿到全部的暴力分. 1(暴力分\(60/100\)) 暂时我可以拿的暴力分为\(30/100\),直接mst模拟即可. 然而当时打了个辣鸡莫队,结果爆 ...
- 【JZOJ5060】【GDOI2017第二轮模拟day1】公路建设 线段树+最小生成树
题面 在Byteland一共有n 个城市,编号依次为1 到n,它们之间计划修建m条双向道路,其中修建第i 条道路的费用为ci. Byteasar作为Byteland 公路建设项目的总工程师,他决定选定 ...
- [jzoj5073 GDOI2017第二轮模拟] 影魔
Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵 ...
- 【JZOJ5064】【GDOI2017第二轮模拟day2】友好城市 Kosarajo算法+bitset+ST表+分块
题面 在Byteland 一共有n 座城市,编号依次为1 到n,这些城市之间通过m 条单向公路连接. 对于两座不同的城市a 和b,如果a 能通过这些单向道路直接或间接到达b,且b 也能如此到达a,那么 ...
- 【JZOJ5086】【GDOI2017第四轮模拟day1】数列 折半搜索
题面 有一个长度为n 的排列,现在有一些位置的数已经模糊不清了,你只知道这个排列的逆序对个数是K,你能计算出总共有多少可能的排列吗? 对于100% 的数据,n <=10^3,K<=10^9 ...
- 【JZOJ5071】【GDSOI2017第二轮模拟】奶酪 树形dp
题面 CJY很喜欢吃奶酪,于是YJC弄到了一些奶酪,现在YJC决定和CJY分享奶酪. YJC弄到了n-1块奶酪,于是他把奶酪挂在了一棵n个结点的树上,每根树枝上挂一块奶酪,每块奶酪都有重量. YJC和 ...
- 【JZOJ5068】【GDSOI2017第二轮模拟】树 动态规划+prufer序列
题面 有n个点,它们从1到n进行标号,第i个点的限制为度数不能超过A[i]. 现在对于每个s (1 <= s <= n),问从这n个点中选出一些点组成大小为s的有标号无根树的方案数. 10 ...
- DFRobot万物互联大赛第二轮
前言 最近放在阳台的花草被啥东西给吃了,然后厨房挂在墙上的小虾米也不知道咋的被抓破吃光了(我怀疑是隔隔壁两条泰迪),所以打算做个简单的项目,教训一下偷吃贼.时间比较仓促,内容比较多,能力有比较有限,好 ...
- LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)
LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set $ solution: $ 这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小.于是我 ...
- 【百度之星2014~初赛(第二轮)解题报告】Chess
声明 笔者近期意外的发现 笔者的个人站点http://tiankonguse.com/ 的非常多文章被其他站点转载.可是转载时未声明文章来源或參考自 http://tiankonguse.com/ 站 ...
随机推荐
- 基于sklearn的集成学习实战
集成学习投票法与bagging 投票法 sklearn提供了VotingRegressor和VotingClassifier两个投票方法.使用模型需要提供一个模型的列表,列表中每个模型采用tuple的 ...
- 漫谈计算机网络:应用层 ----- 从DNS域名解析到WWW万维网再到P2P应用
2022-12-04 18:31:01 纪念一下博主的<漫谈计算机网络>连载博客 浏览量破500了! 今天更新完结篇! 面试答不上?计网很枯燥? 听说你学习 计网 每次记了都会忘? 不妨抽 ...
- 【SQL基础】【关键字大写】条件查询:比较、不等于、IN、为空、BETWEEN
〇.概述 1.内容介绍 条件查询:比较.不等于.IN.为空.BETWEEN 2.建表语句 drop table if exists user_profile; CREATE TABLE `user_p ...
- 大规模爬取(新浪为例子)网页之downloader、parser的封装(涉及编码等细节)
import requests import cchardet import traceback from lxml import etree def downloader(url,timeout = ...
- JAVA学到方法写了一个四则运算计算器,请教一下有什么需要改进的
package method; /* * 四则运算计算器 * */ import java.util.Scanner; public class Demo07 { public static void ...
- 【深入浅出SpringCloud原理及实战】「SpringCloud-Alibaba系列」微服务模式搭建系统基础架构实战指南及版本规划踩坑分析
Spring Cloud Alibaba Nacos Discovery Spring Boot 应用程序在服务注册与发现方面提供和 Nacos 的无缝集成. 通过一些简单的注解,您可以快速来注册一个 ...
- week_3
Andrew Ng机器学习笔记 Week_3 -- -Logistic Regression This week, we'll be covering logistic regression. Log ...
- C++可执行文件绝对路径获取与屏蔽VS安全检查
:前言 前几天写新项目需要用到程序所在绝对路径的时候,发现网上居然一点相关分享都没有. :_pgmptr 翻箱倒柜找出了几本教程,发现了一个叫_pgmptr的东西. 进去看了一下,在stdlib.h里 ...
- TensorRT基础笔记
一,概述 TensorRT 是 NVIDIA 官方推出的基于 CUDA 和 cudnn 的高性能深度学习推理加速引擎,能够使深度学习模型在 GPU 上进行低延迟.高吞吐量的部署.采用 C++ 开发,并 ...
- Jasypt与Apollo一起使用造成Apollo热更新失效问题分析
背景 近日业务同学反映在Apollo界面更改配置后, 服务中对应变量的值却没有改变 相关配置key定义如下: @ApolloJsonValue("${apollo.config.map:{} ...