1 条题解
-
0
题意
给定一个序列,我们需要遍历所有不同的 。为了最大化某个值,我们遍历所有整数 (满足 能被 整除),范围从 到 ,其中 是序列中最大值的两倍。对于每个这样的 ,我们需要找到最大的 ,使得 。由于数值范围有限,我们可以用数组在 时间内完成这个查找。然后根据找到的 更新答案。
思路
- 枚举序列中所有不同的元素 。
- 对于每个 ,枚举其倍数 (从 到 )。
- 对于每个 ,快速找到小于 的最大 (通过预处理数组实现)。
- 利用这个 更新答案。
- 时间复杂度为 。
算法步骤
- 读入序列,找出最大值 ,令 。
- 预处理一个数组 ,其中 表示小于等于 的最大 。
- 对序列中的每个不同元素 :
- 从 开始,步长为 ,直到 :
- 令 (即小于 的最大 )。
- 用 更新答案。
- 从 开始,步长为 ,直到 :
- 输出最终答案。
复杂度分析
- 时间复杂度:,其中 是序列长度, 是最大值的两倍。
- 空间复杂度:,用于存储预处理数组。
代码说明
- 使用一个数组 标记每个值是否出现,并记录最大值。
- 用另一个数组 预处理每个位置小于等于它的最大出现值。
- 外层循环遍历所有不同的 ,内层循环枚举其倍数 ,通过 快速获取候选值并更新答案。
#include <bits/stdc++.h> using namespace std; const int MAXN=1e6+10; const int MAXK=1e6+10; int n,m,a[MAXN],st[MAXK+20][31],mx,lg[MAXN]; int solve(int l,int r){ int log2r=lg[r-l+1]; return max(st[l][log2r],st[r-(1<<log2r)+1][log2r]); } int main(){ ios::sync_with_stdio(0); cin.tie(0); for(int i=2;i<MAXK;i++)lg[i]=lg[i/2]+1; cin>>n; for(int i=1;i<=n;i++)cin>>a[i],st[a[i]][0]=a[i],mx=max(mx,a[i]); int log2n=lg[mx]; for(int j=1;j<=log2n;j++){ for(int i=0;i<=mx-(1<<j)+1;i++){ st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]); } } int ans=0; for(int i=1;i<=mx;i++){ if(!st[i][0])continue; for(int j=i;j<=mx;j+=i){ int r=solve(j,min(mx,j+i-1)); ans=max(ans,r%i); } } cout<<ans; return 0; }
- 1
信息
- ID
- 6729
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者