Loading

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;
}
posted @ 2026-08-01 15:17  Trent900  阅读(20)  评论(0)    收藏  举报