【loj - 6516】「雅礼集训 2018 Day11」进攻!
description
你将向敌方发起进攻!敌方的防御阵地可以用一个 \(N\times M\) 的 \(01\) 矩阵表示,标为 \(1\) 的表示有效区域,标为 \(0\) 的是敌人的预警装置。
你将发起 \(K\) 轮进攻,每一轮从所有 \(\frac{NM(N+1)(M+1)}{4}\) 种可能中选定一个矩形区域对其进行轰炸。如果 \(K\) 轮后存在一个有效区域每次都被轰炸到,并且没有一次触发敌人的预警装置,那么将对敌人造成致命打击。现在你想知道一共有多少种不同的轰炸方案能对敌人造成致命打击,输出对 \(998244353\) 取模的结果。
solution
如果是树上选连通块要求有交集,可以用 "点 - 边" 的容斥技巧(参考「十二省联考 2019」希望)。
如果是网格图,我们类似地有 "1×1 - 1×2 - 2×1 + 2×2"。这样算出来每种交集恰好贡献 1。
接下来只需要考虑求多少个合法矩形包含某个 "1×1"(其他三种同理)。
可以考虑差分。分别求每个点作为左上角/右上角/左下角/右下角的时候有多少合法矩形,从而计算每个点在差分中的贡献。
这个可以单调栈 \(O(n^2)\) 随便做。
因为要快速幂,总时间复杂度 \(O(n^2\log k)\)。
accepted code
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 2000;
const int MOD = 998244353;
#define rep(i, x, n) for(int i=x;i<=n;i++)
#define per(i, x, n) for(int i=x;i>=n;i--)
inline int add(int x, int y) {x += y; return x >= MOD ? x - MOD : x;}
inline int sub(int x, int y) {x -= y; return x < 0 ? x + MOD : x;}
inline int mul(int x, int y) {return (int)(1LL * x * y % MOD);}
int pow_mod(int b, int p) {
int ret = 1;
for(int i=p;i;i>>=1,b=mul(b,b))
if( i & 1 ) ret = mul(ret, b);
return ret;
}
int a[MAXN + 5][MAXN + 5], N, M, K;
int h[MAXN + 5], stk[MAXN + 5], tp;
int s1[MAXN + 5][MAXN + 5], s2[MAXN + 5][MAXN + 5];
int s3[MAXN + 5][MAXN + 5], s4[MAXN + 5][MAXN + 5];
void init() {
rep(j, 1, M) h[j] = 0;
rep(i, 1, N) {
rep(j, 1, M) h[j] = (a[i][j] ? h[j] + 1 : 0);
int cnt = 0; stk[tp = 1] = 0;
rep(j, 1, M) {
while( tp && h[j] < h[stk[tp]] ) {
int x = stk[tp--];
cnt -= (x - stk[tp])*h[x];
}
cnt += (j - stk[tp])*h[j], stk[++tp] = j, s1[i][j] = cnt;
}
}
rep(j, 1, M) h[j] = 0;
rep(i, 1, N) {
rep(j, 1, M) h[j] = (a[i][j] ? h[j] + 1 : 0);
int cnt = 0; stk[tp = 1] = M + 1;
per(j, M, 1) {
while( tp && h[j] < h[stk[tp]] ) {
int x = stk[tp--];
cnt -= (stk[tp] - x)*h[x];
}
cnt += (stk[tp] - j)*h[j], stk[++tp] = j, s2[i][j] = cnt;
}
}
rep(j, 1, M) h[j] = 0;
per(i, N, 1) {
rep(j, 1, M) h[j] = (a[i][j] ? h[j] + 1 : 0);
int cnt = 0; stk[tp = 1] = 0;
rep(j, 1, M) {
while( tp && h[j] < h[stk[tp]] ) {
int x = stk[tp--];
cnt -= (x - stk[tp])*h[x];
}
cnt += (j - stk[tp])*h[j], stk[++tp] = j, s3[i][j] = cnt;
}
}
rep(j, 1, M) h[j] = 0;
per(i, N, 1) {
rep(j, 1, M) h[j] = (a[i][j] ? h[j] + 1 : 0);
int cnt = 0; stk[tp = 1] = M + 1;
per(j, M, 1) {
while( tp && h[j] < h[stk[tp]] ) {
int x = stk[tp--];
cnt -= (stk[tp] - x)*h[x];
}
cnt += (stk[tp] - j)*h[j], stk[++tp] = j, s4[i][j] = cnt;
}
}
per(i, N, 1) per(j, M, 1) {
s1[i][j] = add(s1[i][j], sub(add(s1[i+1][j], s1[i][j+1]), s1[i+1][j+1]));
s2[i][j] = add(s2[i][j], sub(add(s2[i+1][j], s2[i][j+1]), s2[i+1][j+1]));
s3[i][j] = add(s3[i][j], sub(add(s3[i+1][j], s3[i][j+1]), s3[i+1][j+1]));
s4[i][j] = add(s4[i][j], sub(add(s4[i+1][j], s4[i][j+1]), s4[i+1][j+1]));
}
}
int get(int dx, int dy) {
int ans = 0;
rep(i, dx + 1, N) rep(j, dy + 1, M) {
int x = sub(add(s1[i][j], s4[i+1-dx][j+1-dy]), add(s2[i][j+1-dy], s3[i+1-dx][j]));
ans = add(ans, pow_mod(x, K));
}
return ans;
}
char str[MAXN + 5];
int main() {
scanf("%d%d%d", &N, &M, &K);
rep(i, 1, N) {
scanf("%s", str + 1);
rep(j, 1, M) a[i][j] = str[j] - '0';
}
int ans = 0; init();
ans = add(ans, get(0, 0)), ans = sub(ans, get(1, 0));
ans = sub(ans, get(0, 1)), ans = add(ans, get(1, 1));
printf("%d\n", ans);
}
details
感觉学了这么久,啥也没学会(无奈.jpg)
这种非常套路而且之前见过类似套路的题都做不出来。果然人还是菜啊。
【loj - 6516】「雅礼集训 2018 Day11」进攻!的更多相关文章
- loj#6517. 「雅礼集训 2018 Day11」字符串(回滚莫队)
传送门 模拟赛的时候纯暴力竟然骗了\(70\)分-- 首先对于一堆\(g\)怎么计算概率应该很好想,用总的区间数减去不合法的区间数就行了,简而言之对\(g\)排个序,每一段长为\(d\)的连续序列的区 ...
- Loj #6503. 「雅礼集训 2018 Day4」Magic
Loj #6503. 「雅礼集训 2018 Day4」Magic 题目描述 前进!前进!不择手段地前进!--托马斯 · 维德 魔法纪元元年. 1453 年 5 月 3 日 16 时,高维碎片接触地球. ...
- LOJ #6509. 「雅礼集训 2018 Day7」C
神仙题 LOJ #6509 题意 给定一棵树,点权为0/1,每次随机一个点(可能和之前所在点相同)走到该点并将其点权异或上1 求期望的移动距离使得所有点点权相同 题解 根本不会解方程 容易发现如果一个 ...
- loj 6051 「雅礼集训 2017 Day11」PATH - 多项式 - 钩子公式
题目传送门 传送门 设 $m = \sum_{i = 1}^{n} a_i$. 总方案数显然等于 $\frac{m!}{\prod_{i = 1}^{n} a_i!}$. 考虑这样一个网格图,第 $i ...
- LOJ #6051. 「雅礼集训 2017 Day11」PATH
完了感觉最近留了好多坑的说,这题也是模模糊糊地会一点 首先我们发现题目要求的是单调不上升的序列个数,那么一个套路就是用值减去下标 然后考虑连续位置的限制,这个我们做一个置换然后尽量向后取 这样拿值和位 ...
- LOJ #6050. 「雅礼集训 2017 Day11」TRI
完全不会的数学神题,正解留着以后填坑 将一个口胡的部分分做法,我们考虑计算格点多边形(包括三角形)面积的皮克公式: \[S=a+\frac{1}{2}b-1\text({a为图形内部节点个数,b为边界 ...
- LOJ #6052. 「雅礼集训 2017 Day11」DIV
完了我是数学姿势越来越弱了,感觉这种CXRdalao秒掉的题我都要做好久 一些前置推导 首先我们很容易得出\((a+bi)(c+di)=k \Leftrightarrow ac-bd=k,ad+bc= ...
- LOJ#6503.「雅礼集训 2018 Day4」Magic[容斥+NTT+启发式合并]
题意 \(n\) 张卡牌 \(m\) 种颜色,询问有多少种本质不同的序列满足相邻颜色相同的位置数量等于 \(k\). 分析 首先本质不同不好直接处理,可以将同种颜色的卡牌看作是不相同的,求出答案后除以 ...
- LOJ#6504. 「雅礼集训 2018 Day5」Convex(回滚莫队)
题面 传送门 题解 因为并不强制在线,我们可以考虑莫队 然而莫队的时候有个问题,删除很简单,除去它和前驱后继的贡献即可.但是插入的话却要找到前驱后继再插入,非常麻烦 那么我们把它变成只删除的回滚莫队就 ...
随机推荐
- jquery.min.js v1.10.3版本autocomplete方法会在text前添加搜索出多少项的文本信息 要去除
http://stackoverflow.com/questions/13011127/how-to-remove-change-jquery-ui-autocomplete-helper-text ...
- poj1966枚举源汇点 求最小点割DInic
Cable TV Network Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 4854 Accepted: 2241 ...
- 深入理解JS:执行上下文中的this(一)
目录 执行上下文与执行上下文栈 this 全局环境 函数环境 总结 参考 1.执行上下文与执行上下文栈 (1)什么是执行上下文? 在 JavaScript 代码运行时,解释执行全局代码.调用函数或使用 ...
- js中 addEventListener 和removeEventListener
js中添加事件监听本来是非常常见的事情,但是去除监听一般很少去干,最近项目中需要监听页面显示或者隐藏 代码如下 document.addEventListener(visibilitychange', ...
- 如何理解Java中的自动拆箱和自动装箱?
小伟刚毕业时面的第一家公司就被面试官给问住了... 如何理解Java中的自动拆箱和自动装箱? 自动拆箱?自动装箱?什么鬼,听都没听过啊,这...这..知识盲区... 回到家后小伟赶紧查资料,我透,这不 ...
- PIC单片机的定时器
PIC单片机的定时器有3个 timer0 timer1 timer2 定时器的计算方法 256*k*Tcy=定时时间 (256-Init-value)*k*Tcy=定时时间
- 【图像处理】利用C++编写函数,绘制灰度图像直方图
1. 简介 利用OpenCV读取图像,转换为灰度图像,绘制该灰度图像直方图.点击直方图,控制台输出该灰度级像素个数. 2. 原理 (1) 实现原理较为简单,主要利用了OpenCV读取图像,并转换为灰度 ...
- [JavaWeb基础] 001.简单的JavaWeb代码和Tomcat配置部署
简介: 其实说明白了就是J2EE应用开发,前端可以有很多的展现方式,后端由Java做逻辑运算和数据支撑.适用于创建服务器应用程序和服务,为搭建具有可伸缩性.灵活性.易维护性的商务系统提供了良好的机制. ...
- Python 每日一练(3)
引言 今天的每日一练,学习了一下用Python生成四位的图像验证码,就是我们常常在登录时见到的那种(#`O′) 思路分析 正如常见的那种图像验证码,它是由数字和字母的随机组合产生的,所以我们首先的第一 ...
- Rocket - util - MultiWidthFifo
https://mp.weixin.qq.com/s/CUnrpyQN5LRBR5bxC5u86A 简单介绍MultiWidthFifo的实现. 1. 基本介绍 实现一个输入宽度 ...