P7521 [省选联考 2021 B 卷] 取模
我们充分发扬人类智慧:
将数组从大到小排序后,依次枚举 \(a_k\) 为模数
根据数学直觉,在排序之后,答案中的模数一定不会比最大值小太多
所以我们只取最大值之后的前 5 个点来作为模数,然后二分计算答案
这样速度快得飞起,在 n=200000 时都可以在 121ms 内卡过
#include <bits/stdc++.h>
#define Misaka namespace
#define Network std
using Misaka Network;
const int N = 2e5 + 7;
int n, a[N];
signed main(){
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
sort(a + 1, a + n + 1);
int ans = 0;
for(int i = n; i >= max(1, n - 5); i --){
vector<int> p;
for(int j = 1; j <= n; j ++){
if(i != j) p.push_back(a[j] % a[i]);
} sort(p.begin(), p.end());
for(int j = 0; j < p.size(); j ++){
int idx = lower_bound(p.begin(), p.end(), a[i] - p[j]) - p.begin() - 1;
while(idx >= 0 && idx == j) idx --;
if(idx >= 0) ans = max(ans, (p[idx] + p[j]) % a[i]);
idx = lower_bound(p.begin(), p.end(), 2 * a[i] - p[j]) - p.begin() - 1;
while(idx >= 0 && idx == j) idx --;
if(idx >= 0) ans = max(ans, (p[idx] + p[j]) % a[i]);
}
}
cout << ans << "\n";
return 0;
}

浙公网安备 33010602011771号