【THUPC 2018】赛艇
Problem
Description
Lavender、Caryophyllus、Jasmine、Dianthus现在在玩一款名叫“赛艇”的游戏。
这个游戏的规则是这样的:
- 玩家自由组成两队,一个人当赛艇的艇长,另一个人当侦察兵;
- 每次游戏开始时,双方均拥有由系统生成的某张地图,该地图以01矩阵的形式表示,
1
表示有障碍物,无法通行,0
表示水域空旷,可以通行; - 第一回合,双方的赛艇艇长都要在地图上指定一个出发点,该出发点不能是障碍物,也就是只能为
0
; - 在每个回合中,艇长可以指挥自己的赛艇向上/下/左/右四个方向的某一方向的空旷水域移动一个单位的距离,也就是说只能移向四个方向上的某个
0
上(当然,不能移动出地图之外);在该操作完成之后,必须向对方说出自己在该回合移动的方向; - 双方的侦察兵负责记录每一回合对方赛艇的移动方向,并负责推断此时对方赛艇可能的位置;如果某方的侦察兵推测出对方赛艇此时的精确位置,那么可以向其发射导弹,该侦察兵所在的一方胜利;
现在,Jasmine记录了一些对方赛艇的路径,她想确定一下此时对方所有可能的位置共有几种。由于她不是很擅长计算,所以这个任务就交给你了。
Input Format
输入第一行包含三个正整数 \(n\),\(m\),\(k\),分别表示地图为 \(n\) 行 \(m\) 列,当前游戏已经进行了 \(k\) 轮。
输入第二行到第 \(n+1\) 行为一个 \(n\) 行 \(m\) 列的 01 矩阵,无任何分隔符号,表示地图的具体信息,具体含义如上所示。
输入的最后一行为一个长度为 \(k\) 的字符串 \(s\),仅由字母 w
、a
、s
、d
构成,从前往后第 \(i\) 个字符 \(s_i\) 表示对方在第 \(i\) 轮中,对方赛艇向上/左/下/右移动一个单位距离。
Output Format
输出一行一个正整数,表示在第 \(k\) 轮游戏回合的时候,对方赛艇可能的位置的种数。对于所有输入数据,保证有合法解。
Sample
Input
5 6 5
000000
001001
000100
001000
000001
dwdaa
Output
4
Explanation
Explanation for Input
上图显示了路径序列可视化之后的结果,下图用蓝色标出了此时对方赛艇可能的位置。
Range
\(2\le n,m \le 1500, 1\le k\le 5\times 10^6\)
Algorithm
多项式
Mentality
套路题。
我们将走过的路径可视化,表示为一个矩阵。矩阵中为 \(1\) 的位置表示走到过,反之走不到。
那么这道题就相当于我们能够找到多少个点,满足将矩阵的左上角与这个点对齐后,矩阵中的 \(1\) 与原图中的 \(1\) 不重合。
考虑将矩阵的列数补齐至 \(m\) 列,然后将原图和矩阵分别拆成一维的数组 \(f,g\),即第一行后面接上第二行,第二行后面接上第三行这样的。
然后将矩阵拆出的 \(g\) 数组翻转得到 \(g'\),和 \(f\) 进行卷积得到 \(F\) 。
若 \(f\) 的长度为 \(a\),\(g\) 的长度为 \(b\),不难发现,对于一个满足要求的,原图中可以对齐矩阵左上角而合法的点 \((x,y)\) ,若其在 \(f\) 中对应第 \(i\) 个位置,矩阵的 \((0,0)\) 在 \(g\) 中对应 \(0\),在 \(g'\) 中对应 \(b-1\) ,那么以 \((x,y)\) 为左上角和矩阵相叠的结果将存在于 \(F\) 的第 \(i+b-1\) 中。
我们只需要对那些合法的,有足够空间去作为左上角叠下这个矩阵的点,统计它们在 \(F\) 中对应结果即可。
答案即为这些结果中 \(0\) 的个数。
Code
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define LL long long
#define go(x, i, v) for (int i = hd[x], v = to[i]; i; v = to[i = nx[i]])
#define inline __inline__ __attribute__((always_inline))
LL 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 = 1505, Max_l = 5e6 + 5, mod = 998244353, G = 3;
int n, m, K, ans, dx[5] = {0, -1, 1, 0, 0}, dy[5] = {0, 0, 0, -1, 1};
int lim, bit, rev[Max_l], f[Max_l], g[Max_l];
int s[Max_l], a[Max_n][Max_n];
char S[Max_l];
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;
}
namespace NTT {
void dft(int *f, bool t) {
for (int i = 0; i < lim; i++)
if (rev[i] > i) swap(f[i], f[rev[i]]);
for (int len = 1; len < lim; len <<= 1) {
int Wn = ksm(G, (mod - 1) / (len << 1));
if (!t) Wn = ksm(Wn, mod - 2);
for (int i = 0; i < lim; i += len << 1) {
int Wnk = 1;
for (int k = i; k < i + len; k++, Wnk = 1ll * Wnk * Wn % mod) {
int x = f[k], y = 1ll * Wnk * f[k + len] % mod;
f[k] = (x + y) % mod, f[k + len] = (x - y + mod) % mod;
}
}
}
}
} // namespace NTT
void ntt(int *f, int *g) {
NTT::dft(f, 0), NTT::dft(g, 0);
for (int i = 0; i < lim; i++) f[i] = 1ll * f[i] * g[i] % mod;
NTT::dft(f, 1);
int Inv = ksm(lim, mod - 2);
for (int i = 0; i < lim; i++) f[i] = 1ll * f[i] * Inv % mod;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("5447.in", "r", stdin);
freopen("5447.out", "w", stdout);
#endif
n = read(), m = read(), K = read();
for (int i = 0; i < n; i++) {
scanf("%s", S);
for (int j = 0; j < m; j++) f[i * m + j] = S[j] == '1';
}
scanf("%s", S + 1);
for (int i = 1; i <= K; i++) {
if (S[i] == 'w') s[i] = 1;
if (S[i] == 's') s[i] = 2;
if (S[i] == 'a') s[i] = 3;
if (S[i] == 'd') s[i] = 4;
}
int sx = 0, sy = 0, l = 0, r = 0, u = 0, d = 0;
for (int i = 1; i <= K; i++) {
sx += dx[s[i]], sy += dy[s[i]];
l = min(l, sy), r = max(r, sy), u = min(u, sx), d = max(d, sx);
}
r -= l, sy = -l, l = 0, d -= u, sx = -u, u = 0;
a[sx][sy] = 1;
for (int i = 1; i <= K; i++) a[sx += dx[s[i]]][sy += dy[s[i]]] = 1;
for (int i = 0; i <= d; i++)
for (int j = 0; j < m; j++) g[i * m + j] = a[i][j] == 1;
for (int i = 0; i < (d + 1) * m / 2; i++) swap(g[i], g[(d + 1) * m - i - 1]);
bit = log2(n * m + (d + 1) * m) + 1, lim = 1 << bit;
for (int i = 0; i < lim; i++)
rev[i] = rev[i >> 1] >> 1 | ((i & 1) << (bit - 1));
ntt(f, g);
for (int i = 0; i < n - d; i++)
for (int j = 0; j < m - r; j++) ans += !f[(d + i + 1) * m + j - 1];
cout << ans;
}
【THUPC 2018】赛艇的更多相关文章
- [日常] PKUWC 2018爆零记
吃枣药丸...先开个坑... day -1 上午周测...大翻车... 下午被查水表说明天必须啥啥啥...(当时我差点笑出声) 晚上领到笔记本一枚和一袋耗材(袜子) 然而班会开太晚回去没来得及收拾就晚 ...
- 默 of 2018:年终总结
目录 1 概述:在平凡中求变 2 专业分流:一个时代的终点,我的新起点 2.1 我在专业分流前夕的境况 2.2 专业分流情况概述,以及对一篇文章的回顾 2.3 总结与余绪 2.4 附:关于理科与工科的 ...
- PKUWC 2018 彻底滚粗记
PKUWC 2018 彻底滚粗记 如果你们有看到我又在颓, 请以这篇文章让我回忆起这不堪回首的往事. day -3 据说我们要参加PKUWC? 谢总要求我们练习面试,写个稿子. 不知道为什么,有一种不 ...
- 2018. The Debut Album
http://acm.timus.ru/problem.aspx?space=1&num=2018 真心爱过,怎么能彻底忘掉 题目大意: 长度为n的串,由1和2组成,连续的1不能超过a个,连续 ...
- Math.abs(~2018),掌握规律即可!
Math.abs(~2018) 某前端群的入门问题长姿势了,一个简单的入门问题却引发了我的思考,深深的体会到自己在学习前端技术的同时忽略遗忘了一些计算机的基础知识. 对于 JS Math对象没什么可说 ...
- 肖秀荣8套卷2018pdf下载|2018肖秀荣冲刺8套卷pdf下载电子版
肖秀荣8套卷2018pdf下载|2018肖秀荣冲刺8套卷pdf下载电子版 下载链接: https://u253469.ctfile.com/fs/253469-229815828
- 2018年的UX设计师薪酬预测,你能拿多少?
以下内容由Mockplus团队翻译整理,仅供学习交流,Mockplus是更快更简单的原型设计工具. 一个经验丰富的设计师完全可以根据地区和专业来可以预期薪酬之间的差距,其中悬殊最高可达80K. 本 ...
- Hello 2018, Bye 2017
2017年过去了,过去一年经历了太多,改变了好多好多,可以说人生进入了另一个阶段,有可能是成熟吧. 回顾2017 去年换了新工作,离开了将近工作了8年的公司,不带走一丝云彩,为其任劳任怨,最后没有任何 ...
- New Life With 2018
2017年转眼过去了.对自己来说.这一大年是迷茫和认知的一年.我的第一篇博客就这样记录下自己的历程吧 一:选择 从进入这一行到现在已经一年多了,2016年11月份就像所有的应届毕业生一样,都贼反感毕业 ...
随机推荐
- 在flink中使用jackson JSONKeyValueDeserializationSchema反序列化Kafka消息报错解决
在做支付订单宽表的场景,需要关联的表比较多而且支付有可能要延迟很久,这种情况下不太适合使用Flink的表Join,想到的另外一种解决方案是消费多个Topic的数据,再根据订单号进行keyBy,再在逻辑 ...
- Magicodes.Sms短信库的封装和集成
简介 Magicodes.Sms是心莱团队封装的短信服务库,已提供Abp模块的封装. Nuget 新的包 名称 说明 Nuget Magicodes.Sms.Aliyun 阿里云短信库 Magicod ...
- ajax异步请求的三种常见方式
首先先介绍下ajax,ajax(ASynchronous JavaScript And XML)为异步的javascript和xml.所谓的异步和同步是指: 同步:客户端必须等待服务器的响应,在等待期 ...
- luogu P3152 正整数序列
题目描述 kkk制造了一个序列,这个序列里的数全是由正整数构成的.你别认为她的数列很神奇--其实就是1, 2, -, n而已.当然,n是给定的.kkk的同学lzn认为0是一个好数字(看上去很饱满有木有 ...
- UITableView 实例详解 滑动编辑 headerView
转自:http://blog.csdn.net/reylen/article/details/8505960 self.dataArray = [[[NSMutableArray alloc]init ...
- vmware虚拟机扩大硬盘
记录一下对vmware虚拟机扩大硬盘的过程.操作有风险,重要数据请先进行备份. 1.首先在vcenter中将虚拟机下电,然后编辑虚拟机,将虚拟机硬盘扩大.具体操作见下图 2.打开虚拟机电源,利用fdi ...
- mybatis注解
@select查詢 @insert添加 @delete刪除 @update修改 @Results自关联 @Results映射 @One UserByRole表: RoleByUser表: @Many ...
- 【Java Web开发学习】Spring发布RMI服务
[Java 远程服务]Spring发布RMI服务 转载:https://www.cnblogs.com/yangchongxing/p/9084066.html RmiServiceExporter可 ...
- 7个点说清楚spring cloud微服务架构
前言 spring cloud作为当下主流的微服务框架,让我们实现微服务架构简单快捷,spring cloud中各个组件在微服务架构中扮演的角色如下图所示,黑线表示注释说明,蓝线由A指向B,表示B从A ...
- 有一部分程序员还不知道Java 中的注解到底是如何工作的?
作者:人晓 自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecated这样的注解. 这篇文章中, ...