CF1593D2 题解
题目传送门
蒟蒻做的第二十八道 CF 题!让我们看看题意:
有一个包含
拿到题目后,发现
首先判断
我们也可以探索:当
首先因为不能随意取值,所以这个
所以说,存在两个数
所以我就交了一发将
#include <iostream>
using namespace std;
int t,n,a[105],b[2000005];//a_i是数组,b_i是桶
int main()
{
cin >> t;
while(t --)
{
cin >> n;
for(int i = 1;i <= n;i ++)cin >> a[i];
int maxx = 0;
for(int i = 2000001;i >= 1;i --)
{
for(int j = 1;j <= n;j ++)
{
int k = (a[j] % i + i) % i;//注意负数取模后是负数,一定得将它变成正数
b[k] ++;//如果两个数可以变成相同,那么它们在模k意义下必须同余
if(b[k] >= n - n / 2)
{
maxx = i;
break ;
}
}
for(int j = 1;j <= n;j ++)b[(a[j] % i + i) % i] = 0;
if(maxx)break ;
}
if(maxx > 2e6)cout << "-1\n";
else cout << maxx << '\n';
}
}
看来我们枚举的个数还是太多。让我们优化一下上面的代码:因为存在两个整数
因为一组数据的
这是改进后的代码:
#include <iostream>
#include <algorithm>
using namespace std;
int t,n,a[105],b[2000005],c[200005],cnt = 0;//c数组存储可能的k值
int main()
{
cin >> t;
while(t --)
{
cin >> n,cnt = 0;
for(int i = 1;i <= n;i ++)cin >> a[i];
for(int i = 1;i <= n;i ++)
for(int j = i + 1;j <= n;j ++)
{
int k = abs(a[i] - a[j]);
for(int l = 1;l * l <= k;l ++)
if(k % l == 0)c[++cnt] = l,c[++cnt] = k / l;
}
sort(c + 1,c + cnt + 1);
int cnt2 = unique(c + 1,c + cnt + 1) - c - 1,maxx = 0;//为保证复杂度,记得去重
c[++cnt2] = 2000001;
for(int i = cnt2;i >= 1;i --)
{
for(int j = 1;j <= n;j ++)
{
int k = (a[j] % c[i] + c[i]) % c[i];
b[k] ++;
if(b[k] >= n - n / 2)
{
maxx = c[i];
break ;
}
}
for(int j = 1;j <= n;j ++)b[(a[j] % c[i] + c[i]) % c[i]] = 0;
if(maxx)break ;
}
if(maxx > 2e6)cout << "-1\n";
else cout << maxx << '\n';
}
}
这里也包含了 CF1591D1 的代码,将 n - n / 2 改成 n 即可。话说这道题值不值 *1900 呢?