[ARC-148] A - mod M

0|1原题链接

1|0题意

给你一个序列 A=(A1,A2,...,An) ,你需要对它们进行一次操作

你可以选择一个大于等于 2 的模数 m , 然后将 A 序列的所有元素更新为 Ai mod m

举个例子, 你可以选择 m=4 并将 (2,7,4) 更新为 (2,3,0)

现在,你的任务是寻找一个合适的 m 并输出序列 Am 更新后的不同元素的个数

2|0思路

首先,我们考虑 m=2 的特殊情况

由于取模运算的封闭性,当 m=2 时, 显然答案最大为 2

因此我们证明出答案的上界为 2,而由于更新后 A 数组至少有一个元素,即答案的下界为 1

故我们可以知道答案只会在 1,2 两者之中

我们考虑什么时候答案可以为 1

我们来寻找一个 A 数组和 m,并让答案为 1 :

Ai mod m 均等于 x 时,答案为 1

那么我们可以将 Ai 写作 Ai=km+x

于是有 AiAi1=(kiki1)m,避免负数,我们把 |AiAi1| 写作 ai

可以知道当 i2 取到 n 时,得到的 a 序列,他们的最大公倍数 gcd 的下界为 m

至此,接下来我们来寻找 a 序列的最小公倍数作为模数 m

  • gcd=0

那么根据辗转相除法,此时所有的 Ai 都是相等的,显然答案为 1

  • gcd=1

那么此时他们就没有除了 1 公约数,也就没有一个合适的 m ,于是令 m=2 ,所以答案为 2

  • 对于其他情况

则是此时存在一个 m, 使得更新后的 Ai 均为 x ,所以答案为 1

至此,我们可以在 O(Nlogmax(A[i])) 的时间复杂度内,解决该问题

#include <bits/stdc++.h> using namespace std; const int N = 2e5 + 10; int n, a[N], b[N]; int main(){ cin >> n; for(int i = 1 ; i <= n; i++) scanf("%d", &a[i]); for(int i = 2; i <= n; i++) b[i] = abs(a[i] - a[i - 1]); int gcd = b[2]; for(int i = 3; i <= n; i++) gcd = __gcd(b[i], gcd); if(gcd == 1) puts("2"); else puts("1"); return 0; }

__EOF__

本文作者userName
本文链接https://www.cnblogs.com/P32sx-qq1309267816-tel18081238250/p/16687015.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   P32sx  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示