本文已参与[新人创作礼]活动,一起开启掘金创作之路
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
这是3月15日代码源div2的每日一题,对应cf分数1100。
知识点:最大公因数+哈希表
整齐的数组 - 题目 - Daimayuan Online Judge
Polycarp 有一个长度为 nn 的数组 a1,a2,...,an(n 是偶数)。Polycarp 还得到了一个正整数 k,他开始对数组 a 做如下操作:选择一个下标 i (1≤i≤n)i (1≤i≤n) 使 ai 减去 kk。
在 Polycarp 进行若干次操作后(可能 0 次),数组 a 中的所有数都变成相同的了。请你找到最大的符合要求的 k,如果 k 可以为任意大,请输出 −1。
输入格式
第一行一个整数 t,表示测试单元的个数。
接下来每个测试单元有两行。第一行包含一个偶数 n。第二行包含 n 个整数 a1,a2,...,an。
输出格式
对于每个测试单元输出单独一行一个整数 k (k≥1) —— Polycarp 能用来对数组进行操作的最大的数,或者 −1 —— 如果k 能任意大的话。
样例输入
3
6
1 5 3 1 1 5
8
-1 0 1 -1 0 1 -1 0
4
100 -1000 -1000 -1000
样例输出
2
1
1100
数据规模
所有数据保证 1≤t≤10,4≤n≤40(n 是偶数),−10^6≤ai≤10^6,并且 n 的总和不超过100。
问题解析
这题简单来说,就是把其他数组的数一直减k,减到最小那个数,问这个数最大是多少。虽然题目说了要数组相同,但其实就是变成最小值的意思,比如最小值是x,其他值是y,那么题目的最终要求就是:
x-k * (次数)=y-k * (更多次数) ,即 x=y-k * (更多次数)+k * (次数)。
然后因为所有数都减的是同一个k,只是减的次数不同,这里我们就很容易想到是最大公因数。所以这题我们实际要求的是数组中其他值与最小值的差的最大公因数。
两个数的最大公因数好求,但多个的怎么算呢?我们可以遍历一遍数组找最小的那个数,在算一趟其它数与这个最小数的差值,顺便算算有多少个数与最小值相同。然后我们把那些差值的因数全部求出来并存到哈希表里,如果有哪个因数的数量达到了n-最小值个数,说明这个因数是其它数与最小值的差值所共有的因数,我们在这类因数中取最大值即可。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<map>
int main() {
int t;
cin >> t;
while (t--)
{
int n, res = 0, min_num = 1e9,k=-1;
cin >> n;
vector<int>v(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> v[i];
min_num = min(min_num, v[i]);
}
map<int, int>mymap;
for (int i = 1; i <= n; i++)
{
if (v[i] != min_num)
{
int ans = v[i] - min_num;
for (int j = 1; j * j <= ans; j++)
{
if (ans % j == 0)
{
mymap[j]++;
mymap[ans / j]++;
}
}
}
else
{
res++;
}
}
for (auto i : mymap)
{
if (i.second >= n - res)k = max(k, i.first);
}
cout << k << '\n';
}
return 0;
}