我们考虑在值域上做,设值域为 \(m\) 。
我们可以考虑数论分块,对于一对 \(a_i\) 和 \(a_j\) ,$\left \lfloor \frac{a_i}{a_j} \right \rfloor $ 的取值只有 \(\sqrt{a_i}\) 个,所以我们考虑在相同的取值中取最小的 \(a_j\) 进行更新答案,就可以得到 \(a_i \bmod a_j\) 的最大值。
由于是在值域上做数论分块同时还要维护区间最值,复杂度为 \(O(n\sqrt m~log~m )\) 过不了……
考虑进行优化,我们可以发现这个区间最值是在值域上搞的,可 \(O(m)\) 预处理,然后复杂度降为 \(O(n\sqrt m)\) 。
然后你再最优化剪枝就过了……
以上。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,M=1e6+5;
int n,a[N];
int minn[M];
int ans=0;
bool cmp(int a,int b){return a>b;}
int main()
{
cin>>n,memset(minn,63,sizeof(minn));
for(int i=1;i<=n;++i) scanf("%d",&a[i]),minn[a[i]]=a[i];
for(int i=1e6;i>=1;--i) minn[i]=min(minn[i],minn[i+1]);
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;++i)
{
for(int j=ans+1;j<=a[i];j=a[i]/(a[i]/j)+1)
ans=max(ans,a[i]%minn[j]);
}
printf("%d\n",ans);
return 0;
}
原文:https://www.cnblogs.com/Point-King/p/13653129.html