首页 > 其他分享 >[ABC219F] Cleaning Robot 题解

[ABC219F] Cleaning Robot 题解

时间:2024-03-09 20:44:58浏览次数:18  
标签:一个点 ABC219F int 题解 一轮 Robot 偏移量 贡献 mod

[ABC219F] Cleaning Robot 题解

思路解析

要点:将整个图拆分成每一轮的每一个点单独考虑贡献。

首先看到 \(k \le 10^{12}\) 发现不能直接枚举 \(k\) 轮,于是开始找每一轮的规律。首先可以知道,如果操作固定,那么起点和路径上每一个点以及终点的相对位置不会改变。也就是说每一轮的起点之间的相对位置,我们记作每一轮的偏移量,其实是不会改变的。若不理解,请看下图。

其中红线代表经过的位置和线路,黑线代表起点与各个点之间的偏移量。由此可见不论如何移动起点,它移动所形成的形状是不会改变的。

了解完这个规律之后就很好理解了。我们可以先做出来第一次所经过的所有点的位置,由于起点和终点的偏移量不会改变的特点,我们在以后每一轮的这一个操作完后的位置,和上一轮进行完这一个操作之后的位置,偏移量也是不会改变的。若不理解,请看下图。

其中红点表示第一次经过的点,蓝点表示第二次经过的点,黑线表示第一轮的当前次序遍历到的点与第二轮的当前次序遍历到的点之间的偏移量。可以发现每一个点的位置与下一轮的位置之间的偏移量也是不会变的,而这个偏移量其实就是每一轮的起点和终点的偏移量,因为每一轮的开始都是上一轮的结束,所以每一轮的起点的偏移量是固定的,那么其他点的偏移量也是固定的。所以这时我们发现,有一些点在下一轮到达了未经过的位置,它对答案造成了贡献(如上图最右边的两个蓝色点),而有一些则又经过了之前已经经过了的其他点,就对答案没有贡献(如上图的其他蓝色点)。

接下来我们则需要思考第一轮中有哪些点对答案有贡献,贡献分别是多少。我们考虑下面这幅图。

红,蓝,绿点分别表示第一,二,三轮经过的点。我们发现后两轮造成了贡献的点只有三个,分别是 \((0,0),(0,2),(1,2)\) 这三点。而其中 \((0,0)\) 点只造成了 \(1\) 次贡献,并且可以发现该点以后再也不会造成任何贡献。原因是如果我们把一个点增加 \(1 \to k\) 次偏移量的每一种情况都列举出来,如果中途的第 \(i\) 个点在第一轮就被遍历过了,那么第 \(i \to k\) 这些所有的轮数里当前点都不会再有任何贡献。换句话说,当前点对答案的贡献就是 \(i\),因为还有第一轮造成的贡献。

明确了答案统计的方式之后,我们需要计算的值就是对于第一次移动遍历到的每一个点,找到加上 \(i\) 轮偏移量后会与第一轮经过的某一个点重合的最小的 \(i\)。由于每一轮之间的偏移量不变,所以当前点经过 \(k\) 轮移动后所有的点都在同一条斜率为 \(\frac{x}{y}\) 的直线上,其中 \(x,y\) 分别是偏移量的 \(x,y\) 轴。所以问题就变成了对于每一个点,找到经过当前点的斜率为 \(\frac{x}{y}\) 的直线上往后找与当前点最接近的点,计算当前点需要经过多少轮的偏移量才能到达这个点,也就是将距离除以偏移量的值。这里的点指第一轮中经过的所有点。这样我们就可以把每一条直线给找出来,对于每一条直线都用一个 vector 存下这条直线上所有的点与起点之间经过的轮数,设 \(a,b\) 分别为当前点的 \(x,y\) 轴,起点就是 \((a \mod x,b-y\times\lfloor a/x \rfloor)\)。最后的答案就是对于每一条直线,设 \(v_{i}\) 为当前直线上的第 \(i\) 个点,求 \(\sum_{i=1}^{size-1} \min(v_{i+1}-v_{i},k)+k\),因为如果相差轮数大于 \(k\),那么对答案就没有影响,同时最后一个点不会被阻挡,所以要加上 \(k\)。

最后就是几个需要注意的小细节:

  • 若 \(x=0,y=0\),就说明之后的每一轮都不会有新的贡献,直接输出第一轮的贡献即可。
  • 若 \(x=0,y \ne 0\),为了防止 \(a \mod x\) 没有结果,我们交换 \(x,y\) 和所有的 \(a,b\)。
  • 若 \(x<0\),为方便计算,我们取反 \(x\) 和所有的 \(a\)。

code

#include<bits/stdc++.h>
using namespace std;
#define PII pair<int, int>
#define fir first
#define sec second
string str;
long long k;
vector< PII > v;
int dx[150], dy[150];
void init() {
	dx['U'] = -1;
	dx['D'] = 1;
	dy['L'] = -1;
	dy['R'] = 1;
}
signed main() {
	init();
	cin >> str >> k;
	int x = 0, y = 0;
	v.push_back({x, y});
	for(int i = 0; i < (int)str.size(); i++) {
		x += dx[(int)str[i]], y += dy[(int)str[i]];
		v.push_back({x, y});
	}
	sort(v.begin(), v.end());
	v.erase(unique(v.begin(), v.end()), v.end());
	if(x == 0 && y == 0) {
		cout << v.size(); return 0;
	}
	if(x == 0) {
		swap(x, y);
		for(auto &it : v) swap(it.fir, it.sec);
	}
	if(x < 0) {
		x = -x;
		for(auto &it : v) it.fir = -it.fir;
	}
	map< PII, vector<int> > mp;
	for(auto it : v) {
		int nx = it.fir, ny = it.sec;
		int mod = (nx % x + x) % x;
		mp[{mod, ny - (long long)y * (nx - mod) / x}].push_back((nx - mod) / x);
	}
	long long ans = 0;
	for(auto it : mp) {
		sort(it.sec.begin(), it.sec.end());
		for(int i = 0; i <= (int)it.sec.size() - 2; i++) {
			ans += min(k, (long long)it.sec[i + 1] - it.sec[i]);
		}
		ans += k;
	}
	cout << ans;
	return 0;
}

标签:一个点,ABC219F,int,题解,一轮,Robot,偏移量,贡献,mod
From: https://www.cnblogs.com/2020luke/p/18063254

相关文章

  • CF1583E Moment of Bloom 题解
    题意:给定一张\(n\)个点\(m\)条边无向连通图,以及\(q\)个点对\((a,b)\),出事每条边权值为\(0\)。对于每个点对我们需要找一条从一个点到另一个点的简单路径,将所有边的权值加一。要求构造一种方案使得每条边权值都是偶数。如果不行,输出最少还要几个点对才能满足要求。\(n,m......
  • CF1634E Fair Share 题解
    题意:给定\(m\)个长度为偶数的数组,\(L,R\)是初始为空的两个多重集。将每个数组恰好一半的数放入\(L\),另一半放入\(R\),要求最后\(L=R\),要求构造方案或判断无解。\(m\le10^5,\sumn\le10^5\)。思路:首先我们不难想到,对于同一个数组内相同的值,可以成双除去,所以我们可以......
  • Interval GCD 题解
    题目描述给定一个长度为\(\largen\)的数组\(\largea\),以及\(\largem\)条指令(\(n\leq5\times10^5,m\leq10^5\)),每条指令可能是以下两种之一:“\(\large\operatorname{C\l\r\d}\)”,表示把\(\largea[l],a[l+1],…,a[r]\)都加上\(\larged\)。“\(\large\operatorn......
  • CF1264D2 Beautiful Bracket Sequence (hard version) 题解
    括号深度的本质,其实就是删除若干个字符以后使得左边一半全是(,右边一半全是),最终(的个数的最大值。那么就一定存在一个位置使得在这个位置以及之前的字符中(的个数等于这个字符后)的个数。考虑枚举这个位置,记它左边的(的个数为\(a\)、?的个数为\(x\),右边的)的个数......
  • [CF696B] Puzzles 题解
    首先很好想到要用树形\(dp\)。然后设\(dp_i\)为遍历到第\(i\)个点的期望时间,\(sz_i\)代表\(i\)的子树大小。发现有转移方程:\[dp_i=dp_{fa_i}+1+\sum\limits_{j\infa_i且j\nei}sz_j\timesq\]其中\(q\)为一个常数,代表在排列中\(j\)在\(i\)前的概率。很容易发......
  • 无聊的数列[题解]
    无聊的数列[link1][link2]题目大意给定一个数列\(A\)有两种操作:将数列中\(A_i\)(\(L\leqi\leqR\))加上一个等差数列(首项D公差K)查询数列中第P位数区间加上一个等差数列可以用差分来解决例原序列:000000差分序列:000000等差序列:13579(首项1......
  • 课堂练习 最大值 原题链接+题解
    题目可以去我的洛谷题库看:https://www.luogu.com.cn/problem/U412348(带数据,真难出)题解考虑两种解题方式。由于题目范围较小,可以check+暴力,如果范围大一点,可以check+二分答案。先讲check函数,小学四年级数学书说了,这种问题也被它叫做“铺地砖”问题,计算剪出的正方形数量的方......
  • 一本通 1270 混合背包 题解
    是在hydro上做的,墙裂推荐hydro的一本通题库!链接是:https://hydro.ac/d/ybttk/p/T1270。分析一下,可以分类讨论,处理的时候,零一背包(\(p_i=1\))一个,完全背包(\(p_i=0\))一个,多重背包(\(p_i>1\))一个,状态转移方程不用列的,直接去抄模板就可以啦~代码是这样的捏:#include<bits/st......
  • P6583 回首过去 题解
    P6583回首过去题解题目传送门好题。更新(2023-12-05):把代码和$\LaTeX$改得更好看了。题意简述给定正整数$n$,求出有序整数对$(x,y)$的个数,满足$1\lex,y\len$且$\dfracxy$可以表示为十进制有限小数。$1\len\le10^{12}$。前置知识数论分块解法Subtas......
  • CF1846D Rudolph and Christmas Tree 题解
    因为\(n\)个三角形有重叠部分,所以我们可以倒序处理每个三角形,并对其进行分类讨论:若当前三角形编号为\(n\),则直接将总面积加上\(\dfrac{d\timesh}{2}\)。否则,再次分出两种情况:若当前三角形的\(y_i+h>y_{i+1}\)(即编号为\(i,i+1\)的三角形有重叠),则如下图所示:......